Cours NestJS · Module 10: Validation des données

Décorateurs de validation avancés

3 min de lecture
Dans cette leçon6

Tu connais déjà assez bien les gardes de base de la porte. Il est maintenant temps de rencontrer les gardes d'élite - les décorateurs avancés de class-validator qui gèrent des situations plus complexes.

@IsOptional() - le garde des valeurs optionnelles

Tous les champs ne doivent pas être obligatoires. Le décorateur @IsOptional() dit : « Si ce champ existe, vérifie-le. S'il n'existe pas - laisse-le passer » :

1import { IsOptional, IsString, IsNumber } from 'class-validator';
2
3export class UpdateLegionaryDto {
4  @IsOptional()
5  @IsString()
6  nickname?: string;  // May not have a nickname
7
8  @IsOptional()
9  @IsNumber()
10  bonusPay?: number;  // Bonus pay is optional
11}

@IsEnum() - le garde des valeurs autorisées

Lorsqu'un champ ne peut accepter que des valeurs spécifiques, nous utilisons @IsEnum(). C'est comme une liste des grades autorisés dans la légion :

1import { IsEnum } from 'class-validator';
2
3enum LegionaryRank {
4  MILES = 'miles',
5  OPTIO = 'optio',
6  CENTURIO = 'centurio',
7  LEGATUS = 'legatus',
8}
9
10export class CreateLegionaryDto {
11  @IsEnum(LegionaryRank)
12  rank: LegionaryRank;
13  // 'centurio', 'imperator'
14}

@IsArray() et @ArrayMinSize() - les gardes des tableaux

Lorsque tu attends un tableau de données, tu as besoin de gardes spéciaux :

1import { IsArray, ArrayMinSize, IsString } from 'class-validator';
2
3export class CreateLegioDto {
4  @IsArray()
5  @ArrayMinSize(1)
6  @IsString({ each: true })
7  skills: string[];
8  // ["combat", "march"], [], "combat"
9}

Remarque le { each: true } - ce paramètre indique au décorateur @IsString() de vérifier chaque élément du tableau, et non le tableau lui-même.

@IsDateString() - le garde des dates

Vérifie si la valeur est une chaîne de date valide au format ISO 8601 :

1import { IsDateString } from 'class-validator';
2
3export class CreateEventDto {
4  @IsDateString()
5  enlistmentDate: string;
6  // "2024-03-15T10:00:00Z", "yesterday"
7}

@Matches() - le garde des motifs (regex)

Le garde le plus universel - vérifie si la valeur correspond à une expression régulière :

1import { Matches, IsString } from 'class-validator';
2
3export class CreateLegionaryDto {
4  @IsString()
5  @Matches(/^LEG-[A-Z]{3}-\d{4}$/, {
6    message: 'Military ID must have the format LEG-XXX-0000',
7  })
8  militaryId: string;
9  // "LEG-ROM-0042", "123ABC"
10}

Exemple complet - Formulaire de recrutement de la légion

Combinons tous les décorateurs avancés dans un DTO complet :

1import {
2  IsString,
3  IsNotEmpty,
4  IsEnum,
5  IsOptional,
6  IsArray,
7  ArrayMinSize,
8  IsDateString,
9  Matches,
10  IsNumber,
11  Min,
12  Max,
13  MinLength,
14} from 'class-validator';
15
16enum LegionaryRank {
17  MILES = 'miles',
18  OPTIO = 'optio',
19  CENTURIO = 'centurio',
20  LEGATUS = 'legatus',
21}
22
23export class RecruitLegionaryDto {
24  @IsString()
25  @IsNotEmpty()
26  @MinLength(2)
27  name: string;
28
29  @IsEnum(LegionaryRank)
30  rank: LegionaryRank;
31
32  @IsNumber()
33  @Min(16)
34  @Max(65)
35  age: number;
36
37  @IsDateString()
38  enlistmentDate: string;
39
40  @Matches(/^LEG-[A-Z]{3}-\d{4}$/)
41  militaryId: string;
42
43  @IsArray()
44  @ArrayMinSize(1)
45  @IsString({ each: true })
46  skills: string[];
47
48  @IsOptional()
49  @IsString()
50  nickname?: string;
51}

Avec ces décorateurs dans ton arsenal, tu peux valider pratiquement n'importe quelle donnée. Les gardes de la porte de ton API sont désormais bien entraînés !

Code de cette leçon : src/advanced-decorators.ts
1// Décorateurs de validation avancés
2import {
3  IsString,
4  IsNotEmpty,
5  IsEnum,
6  IsOptional,
7  IsArray,
8  ArrayMinSize,
9  IsDateString,
10  Matches,
11  IsNumber,
12  Min,
13} from 'class-validator';
14
15// Enums de grade de légionnaire
16enum LegionaryRank {
17  MILES = 'miles',
18  OPTIO = 'optio',
19  CENTURIO = 'centurio',
20  LEGATUS = 'legatus',
21}
22
23// TODO : Compléter le DTO avec des décorateurs avancés
24export class RecruitLegionaryDto {
25  @IsString()
26  @IsNotEmpty()
27  name: string;
28
29  // TODO : Ajouter @IsEnum avec LegionaryRank
30  rank: LegionaryRank;
31
32  @IsNumber()
33  @Min(16)
34  age: number;
35
36  // TODO : Ajouter @IsDateString()
37  enlistmentDate: string;
38
39  // TODO : Ajouter @Matches avec la regex /^LEG-[A-Z]{3}-\d{4}$/
40  militaryId: string;
41
42  // TODO : Ajouter @IsArray, @ArrayMinSize(1), @IsString({ each: true })
43  skills: string[];
44
45  // TODO : Ajouter @IsOptional() et @IsString()
46  nickname?: string;
47}
48
49console.log('Décorateurs avancés prêts !');
50

Tu as repéré une erreur dans cette leçon ?

Teste tes connaissances

Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.

  1. 1. Que fait le décorateur @IsOptional() dans class-validator ?

  2. 2. À quoi sert le décorateur @IsEnum() dans class-validator ?

Voici 2 des 3 questions de cette leçon. Réponds aux autres dans le jeu.

Tâches pratiques dans le jeu

  • Éditeur de code

    Complète l'enum ProvinceType et ajoute les décorateurs de validation à CreateProvinceDto

  • Tri vertical

    Range les décorateurs du moins au plus restrictif :

  • Éditeur de code

    Complète les décorateurs @Matches et @IsDateString dans CreateDocumentDto

  • Clique dans l'ordre

    Range les éléments du décorateur @Matches dans le bon ordre :