Skip to content
Learni
Voir tous les tutoriels
JavaScript

Comment maîtriser Yup pour la validation experte en 2026

Read in English

Introduction

Yup, bibliothèque de validation schématique pour JavaScript et TypeScript, transcende les validateurs basiques en offrant une API fluide et expressive pour modéliser des contraintes complexes. En 2026, avec l'essor des APIs microservices, des formulaires React dynamiques et des pipelines CI/CD, une validation rigoureuse n'est plus optionnelle : elle est le rempart contre les injections, les corruptions de données et les crashes en production. Contrairement à des outils comme Joi ou Zod qui priorisent la performance brute ou l'inférence de types, Yup excelle dans la lisibilité sémantique et la composabilité, permettant de décrire des schémas comme des récits logiques : un utilisateur doit avoir un email valide ET un âge supérieur à 18 SI il est majeur.

Ce tutoriel expert, purement conceptuel, dissèque la théorie sous-jacente : des validateurs atomiques aux transformations lazy, en passant par les tests asynchrones. Vous apprendrez à raisonner en schémas plutôt qu'en regex, à anticiper les cas edge comme les unions discriminantes ou les validations dépendantes de contexte. Pourquoi c'est crucial ? Une mauvaise validation coûte 10x plus en debugging qu'en conception upfront. Imaginez valider un payload GraphQL avec 50 champs imbriqués : Yup transforme ce chaos en un arbre cohérent, réutilisable et testable. Prêt à passer de l'artisanat à l'architecture ? (142 mots)

Prérequis

  • Maîtrise avancée de JavaScript ES2023+ et TypeScript 5.5+
  • Expérience avec des bibliothèques de validation (Joi, Zod, Valibot)
  • Compréhension des patterns fonctionnels : higher-order functions, currying
  • Familiarité avec les flux de données asynchrones (Promises, async/await)
  • Connaissances en conception de schémas (JSON Schema, OpenAPI)

Fondamentaux théoriques des validateurs atomiques

Yup repose sur une hiérarchie de validateurs atomiques : string(), number(), boolean(), date(), array(), object() et mixed(). Chaque validateur est un monade fonctionnel encapsulant un état (valide/invalide) et des transformations chaînées. Théoriquement, c'est une implémentation de schema validation par composition, inspirée des monades Haskell : bind() pour les validations séquentielles, map() pour les transformations.

Exemple concret : pour un champ age, chainnez number().positive().integer().min(18). Ici, positive() rejette les négatifs via une garde mathématique stricte ; min(18) applique une contrainte bornée. Analogie : comme un pipeline Unix, chaque .method() filtre et pipe les données, court-circuitant à la première erreur pour une performance O(n).

Pitfall conceptuel : confondre validation (rejet pur) et transformation (sanitization). Utilisez .transform() pour normaliser (ex. : trim strings), mais toujours après validation pour éviter les faux positifs.

Construction de schémas objets et arrays imbriqués

Les schémas object() modélisent des DTO complexes via .shape({}), où chaque clé est un sous-schéma. Pour les arrays, array().of(schémaÉlément) gère l'homogénéité, avec .min(1).max(10) pour les cardinalités.

Cas d'étude : un panier e-commerce. Schéma racine : object().shape({ items: array().of(object().shape({ productId: string().uuid(), quantity: number().int().min(1) })) }). Théorie : cela crée un graphe acyclique dirigé (DAG) de dépendances, évalué en post-ordre (feuilles d'abord).

Avancé : .concat() pour merger schémas réutilisables, comme un baseUser.concat(adminFields). Analogie : Lego modulaire, où object().pick(['email']) extrait des sous-ensembles, idéal pour les partial updates PATCH.

Pour les unions, mixed().oneOf([schémaA, schémaB]) teste exhaustivement, mais préférez union([schémaA, schémaB]) pour la performance (premier match).

Validations conditionnelles et dépendantes

Le cœur expert de Yup : .when('field', { is: value, then: schémaStrict, otherwise: schémaLax }). Cela implémente une logique propositionnelle : si path === 'role' est 'admin', alors exiger permissions: array().min(5).

Exemple concret : formulaire d'inscription. object().shape({ hasPhone: boolean(), phone: string().when('hasPhone', { is: true, then: string().matches(/^\d{10}$/) }) }). Théorie : évaluation lazy (conditions évaluées seulement si nécessaires), évitant les validations inutiles (gain 40% perf sur objets larges).

Avancé : .test('nomTest', 'message', (value, context) => context.parent.otherField > value ). context expose l'objet entier, habilitant des validations cross-fields comme total > sum(items). Analogie : un système d'experts rules-engine, où when est un if-then-else distribué.

Pour async : .test('asyncCheck', async (value, context) => await db.exists(value)), avec support natif des Promises.

Intégration TypeScript et inférence avancée

Yup + TS = type safety totale via InferType. Théorie : générique Schema infère T des contraintes, garantissant validate(input): Promise>.

Pattern expert : const UserSchema = object({...}).defined(); type User = InferType;. .defined() force non-nullable, .nullable() pour optionnels.

Étude de cas : API NestJS. Définissez schéma → inférez DTO → utilisez en controller. Avantage : compile-time checks sur routes, éliminant 90% des runtime errors.

Lazy schemas : lazy(value => value ? complexSchema : simpleSchema), pour polymorphisme runtime. Analogie : pattern Strategy, où le schéma s'auto-adapte comme un plugin.

Bonnes pratiques essentielles

  • Réutilisez via factories : const baseSchema = object({...}); export const createUserSchema = baseSchema.concat(extraFields); pour DRY.
  • Séparez validation et transformation : Validez d'abord, transformez ensuite (schema.validateSync(data, {stripUnknown: true}) pour sanitization).
  • Contextualisez les erreurs : Utilisez .label('Champ lisible') et custom .test() pour messages i18n via context.createError({ message: t('error.key') }).
  • Benchmarkez et profilez : Pour >100 champs, pré-validez atomiquement ; utilisez schema.validateAt('path.nested', partialData) pour validations partielles.
  • Testez exhaustivement : Couvrez happy paths, edges (NaN, Infinity), et fuzzing avec fast-check pour générer inputs mutants.

Erreurs courantes à éviter

  • Sur-chaîner sans short-circuit : Évitez .required().email().min(5) si required() échoue déjà ; Yup optimise nativement.
  • Ignorer le contexte : Toujours passer context: { userId, locale } pour des validations dynamiques.
  • Méconnaître lazy vs when : lazy() pour runtime polymorphisme, when() pour conditions statiques ; mixer cause perf drops.
  • Oublier les casts TS : InferType infère strictement ; utilisez AnyObject seulement en dernier recours pour legacy code.

Pour aller plus loin

  • Documentation officielle : Yup GitHub
  • Alternatives avancées : Comparez avec Zod pour inférence pure TS
  • Patterns réels : Intégrez dans React Hook Form ou tRPC
  • Formations expertes : Maîtrisez la validation full-stack avec nos formations Learni sur TypeScript avancé et APIs sécurisées.
  • Ressource bonus : JSON Schema to Yup converter pour migrations.
Comment maîtriser Yup validation experte 2026 | Learni