Skip to content

Contraintes

Une contrainte permet de définir une règle que le typage ne pourra pas vérifier à lui seul. Par exemple, une contrainte peut vérifier qu'une chaîne de caractères respecte un format particulier (email, URL, …), ou qu'un nombre est dans une certaine plage. Une contrainte s'applique à une primitive.

Fonctionnement

Une contrainte est créée à partir :

  • d'une primitive (ex: C.String, C.Number)
  • d'un ou plusieurs checkers du DDataParser (DP.checkerEmail(), DP.checkerInt(), ...)

Au runtime, une contrainte valide la valeur, puis ajoute un marquage interne (par nom de contrainte). Côté TypeScript, ce marquage se reflète dans le type : on peut alors écrire des fonctions qui acceptent « n'importe quelle valeur portant cette contrainte », qu'il s'agisse d'une primitive contrainte ou d'un NewType qui embarque la même contrainte.

Exemple

Ensembles de contraintes

Quand vous devez appliquer plusieurs contraintes ensemble, vous pouvez créer un ensemble réutilisable avec C.createConstraintsSet(...).

Erreurs des ensembles de contraintes

Les méthodes create() et createWithUnknown() d'un ensemble retournent un Left<"createConstraintsSetError", C.ConstraintError<...>> en cas d'échec. Cette erreur contient :

  • constraintName : le nom de la contrainte associée au checker qui a échoué
  • dataParserError : l'erreur complète du DDataParser

Les méthodes createOrThrow() et createWithUnknownOrThrow() lèvent C.CreateConstraintsSetError avec les mêmes informations, plus la donnée reçue. Les variantes createWithLarge() et createWithLargeOrThrow() suivent les mêmes règles d'erreur, mais acceptent uniquement le type d'entrée large connu par le handler.

Quand l'échec vient d'un checker de contrainte, constraintName correspond à la contrainte qui contient ce checker, même si cette contrainte provient d'un autre ensemble imbriqué. Si l'échec arrive avant l'exécution des contraintes, par exemple parce que la primitive ne peut pas parser la valeur, aucun checker de contrainte n'est responsable. Dans ce cas, l'implémentation utilise le premier nom de contrainte de l'ensemble comme fallback pour constraintName.

Créer une contrainte

Pour créer une contrainte, utilisez C.createConstraint(name, primitive, checker) puis récupérez son type via C.GetConstraint.

Ce type (ex: SlugConstraint) sert ensuite :

  • comme « contrat » (ex: paramètre de fonction)
  • comme contrainte à appliquer lors de la création d'un NewType (C.createNewType(..., SlugConstraint))

Méthodes et Propriétés

Une contrainte est un handler (comme une primitive). Elle expose donc des méthodes de création/validation et quelques propriétés.

Méthodes

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>

Lève C.CreateConstrainedTypeError en cas d'échec de validation.

createWithLarge()

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

Accepte le type d'entrée large porté par la primitive ou par les contraintes. C'est utile lorsqu'une contrainte affine le type de sortie, mais que la source de données reste typée plus largement, par exemple lors d'une hydratation depuis une base de données.

createWithLargeOrThrow()

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

Lève C.CreateConstrainedTypeError ou C.CreateConstraintsSetError en cas d'échec de validation.

createWithUnknown()

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

createWithUnknownOrThrow()

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

Lève C.CreateConstrainedTypeError en cas d'échec de validation.

is()

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

Propriétés

name

Le nom unique de la contrainte (ex: "email", "int", ...).

Contraintes fournies par la librairie

La librairie exporte quelques contraintes prêtes à l'emploi via C.* :

Email

Valide une chaîne au format email.

Url

Valide une chaîne au format URL.

Uuid

Valide une chaîne au format UUID.

NoBlank

Valide une chaîne non vide sans caractères d'espacement.

StringMin

Valide une chaîne avec une longueur minimale (>= min).

StringMax

Valide une chaîne avec une longueur maximale (<= max).

Int

Valide un nombre entier.

Positive

Valide un nombre positif ou nul (>= 0).

StrictPositive

Valide un nombre strictement positif (> 0).

Negative

Valide un nombre négatif ou nul (<= 0).

StrictNegative

Valide un nombre strictement négatif (< 0).

NumberMin

Valide un nombre supérieur ou égal à min.

NumberMax

Valide un nombre inférieur ou égal à max.

NotZero

Valide un nombre différent de zéro.

PositiveTime

Valide une durée strictement positive (>= 1 milliseconde) sur la primitive C.Time.

NegativeTime

Valide une durée strictement négative (<= -1 milliseconde) sur la primitive C.Time.

Ensembles de contraintes fournis par la librairie

La librairie exporte aussi des ensembles de contraintes prêts à l'emploi via C.*. Ils regroupent plusieurs contraintes et peuvent être utilisés directement avec C.createNewType(...) ou comme handlers de validation.

PositiveInt

Valide un nombre entier positif ou nul (Positive + Int).

StrictPositiveInt

Valide un nombre entier strictement positif (StrictPositive + Int).

NegativeInt

Valide un nombre entier négatif ou nul (Negative + Int).

StrictNegativeInt

Valide un nombre entier strictement négatif (StrictNegative + Int).

Percent

Valide un nombre compris entre 0 et 100 inclus (NumberMin(0) + NumberMax(100)).

Voir aussi

Diffusé sous licence MIT.