Skip to content

Constraints

A constraint lets you define a rule that typing alone cannot check. For example, a constraint can verify that a string matches a particular format (email, URL, …), or that a number is within a certain range. A constraint applies to a primitive.

How it works

A constraint is created from:

  • a primitive (e.g. C.String, C.Number)
  • one or more DDataParser checkers (DP.checkerEmail(), DP.checkerInt(), ...)

At runtime, a constraint validates the value, then adds an internal marking (by constraint name). On the TypeScript side, this marking is reflected in the type: you can then write functions that accept “any value carrying this constraint”, whether it is a constrained primitive or a NewType that embeds the same constraint.

Example

Constraints sets

When you need to apply several constraints together, you can build a reusable set with C.createConstraintsSet(...).

Constraints set errors

The create() and createWithUnknown() methods of a set return a Left<"createConstraintsSetError", C.ConstraintError<...>> when validation fails. This error contains:

  • constraintName: the name of the constraint linked to the checker that failed
  • dataParserError: the full DDataParser error

The createOrThrow() and createWithUnknownOrThrow() methods throw C.CreateConstraintsSetError with the same information, plus the received data. The createWithLarge() and createWithLargeOrThrow() variants follow the same error rules, but only accept the wider input type known by the handler.

When the failure comes from a constraint checker, constraintName is the constraint that owns this checker, even when that constraint comes from another nested constraints set. If the failure happens before constraints run, for example because the primitive cannot parse the value, no constraint checker is responsible. In that case, the implementation uses the first constraint name of the set as the fallback constraintName.

Create a constraint

To create a constraint, use C.createConstraint(name, primitive, checker) then get its type via C.GetConstraint.

This type (e.g. SlugConstraint) is then used:

  • as a “contract” (e.g. function parameter)
  • as a constraint to apply when creating a NewType (C.createNewType(..., SlugConstraint))

Methods and Properties

A constraint is a handler (like a primitive). It therefore exposes creation/validation methods and a few properties.

Methods

create()

typescript
function create(
	value: RawType | Primitive<RawType>
): Right<ConstrainedType<ConstraintName, RawType>> | Left<C.ConstraintError<ConstraintName>>

createOrThrow()

typescript
function createOrThrow(
	value: RawType | Primitive<RawType>
): ConstrainedType<ConstraintName, RawType>

Throws C.CreateConstrainedTypeError if validation fails.

createWithLarge()

typescript
function createWithLarge(
	value: LargeInput
): Right<ConstrainedType<ConstraintName, RawType>> | Left<C.ConstraintError<ConstraintName>>

Accepts the wider input type carried by the primitive or by the constraints. This is useful when a constraint refines the output type, but the data source remains typed more broadly, for example when hydrating from a database.

createWithLargeOrThrow()

typescript
function createWithLargeOrThrow(
	value: LargeInput
): ConstrainedType<ConstraintName, RawType>

Throws C.CreateConstrainedTypeError or C.CreateConstraintsSetError if validation fails.

createWithUnknown()

typescript
function createWithUnknown(
	value: unknown
): Right<ConstrainedType<ConstraintName, RawType>> | Left<C.ConstraintError<ConstraintName>>

createWithUnknownOrThrow()

typescript
function createWithUnknownOrThrow(
	value: unknown
): ConstrainedType<ConstraintName, RawType>

Throws C.CreateConstrainedTypeError if validation fails.

is()

typescript
function is(
	value: unknown
): value is ConstrainedType<ConstraintName, RawType>

Properties

name

The unique name of the constraint (e.g. "email", "int", ...).

Constraints provided by the library

The library exports a few ready-to-use constraints via C.*:

Email

Validates a string in email format.

Url

Validates a string in URL format.

Uuid

Validates a string in UUID format.

NoBlank

Validates a non-empty string without whitespace characters.

StringMin

Validates a string with a minimum length (>= min).

StringMax

Validates a string with a maximum length (<= max).

Int

Validates an integer.

Positive

Validates a positive or zero number (>= 0).

StrictPositive

Validates a strictly positive number (> 0).

Negative

Validates a negative or zero number (<= 0).

StrictNegative

Validates a strictly negative number (< 0).

NumberMin

Validates a number greater than or equal to min.

NumberMax

Validates a number less than or equal to max.

NotZero

Validates a number different from zero.

PositiveTime

Validates a strictly positive duration (>= 1 millisecond) on the C.Time primitive.

NegativeTime

Validates a strictly negative duration (<= -1 millisecond) on the C.Time primitive.

Constraint sets provided by the library

The library also exports ready-to-use constraint sets via C.*. They group multiple constraints and can be used directly with C.createNewType(...) or as validation handlers.

PositiveInt

Validates a positive or zero integer (Positive + Int).

StrictPositiveInt

Validates a strictly positive integer (StrictPositive + Int).

NegativeInt

Validates a negative or zero integer (Negative + Int).

StrictNegativeInt

Validates a strictly negative integer (StrictNegative + Int).

Percent

Validates a number between 0 and 100 included (NumberMin(0) + NumberMax(100)).

See also

Released under the MIT license.