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
DDataParsercheckers (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 faileddataParserError: the fullDDataParsererror
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()
function create(
value: RawType | Primitive<RawType>
): Right<ConstrainedType<ConstraintName, RawType>> | Left<C.ConstraintError<ConstraintName>>createOrThrow()
function createOrThrow(
value: RawType | Primitive<RawType>
): ConstrainedType<ConstraintName, RawType>Throws C.CreateConstrainedTypeError if validation fails.
createWithLarge()
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()
function createWithLargeOrThrow(
value: LargeInput
): ConstrainedType<ConstraintName, RawType>Throws C.CreateConstrainedTypeError or C.CreateConstraintsSetError if validation fails.
createWithUnknown()
function createWithUnknown(
value: unknown
): Right<ConstrainedType<ConstraintName, RawType>> | Left<C.ConstraintError<ConstraintName>>createWithUnknownOrThrow()
function createWithUnknownOrThrow(
value: unknown
): ConstrainedType<ConstraintName, RawType>Throws C.CreateConstrainedTypeError if validation fails.
is()
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)).
