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.