Aller au contenu
NestJS OpenPartie 4, section b
Changer de langue : lire en anglais

b · class-validator

  • Projet : Loup-Garou
  • Environ 40 minutes
  • 4 exercices

class-validator ajoute des règles à un DTO, sous forme de décorateurs — encore une fois, le même principe qu’en partie 1. class-transformer l’accompagne : il transforme le JSON brut reçu en véritable instance de ta classe, pour que les décorateurs aient quelque chose à inspecter.

Fenêtre de terminal
npm install class-validator class-transformer
src/villages/dto/creer-village.dto.ts
import { IsArray, IsInt, IsString, Min } from 'class-validator';
export class CreerVillageDto {
@IsInt()
@Min(3)
nombreDeJoueurs: number;
@IsArray()
@IsString({ each: true })
rolesEnJeu: string[];
}

Ces décorateurs seuls ne suffisent pas : il faut dire à NestJS de les faire respecter. C’est le rôle de ValidationPipe, à activer une fois pour toute l’application :

src/main.ts
import { NestFactory } from '@nestjs/core';
import { ValidationPipe } from '@nestjs/common';
import { AppModule } from './app.module.js';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe());
await app.listen(process.env.PORT ?? 3000);
}
await bootstrap();

À partir de là, un village créé avec nombreDeJoueurs: 1 reçoit un 400, avec le détail de chaque règle violée :

{
"message": ["nombreDeJoueurs must not be less than 3"],
"error": "Bad Request",
"statusCode": 400
}

@IsOptional() dispense un champ des autres décorateurs quand il est absent — mais continue de les appliquer s’il est présent. whitelist: true, dans les options de ValidationPipe, retire silencieusement les champs qui n’ont aucun décorateur dans le DTO ; forbidNonWhitelisted: true les rejette carrément au lieu de les ignorer :

app.useGlobalPipes(new ValidationPipe({ whitelist: true, forbidNonWhitelisted: true }));

Sans ça, un client pourrait glisser un champ que ton DTO n’attend pas — sans que rien ne le signale.

Exercices 4.4 à 4.7

Projet : marketplace

Installe class-validator et class-transformer. Ajoute @IsString() @IsNotEmpty() sur nom, @IsNumber() @Min(0) sur prix, @IsIn([...]) sur categorie avec une liste fixe de catégories autorisées. Active ValidationPipe globalement dans main.ts. Rejoue les deux requêtes de l’exercice 4.3 : elles doivent maintenant échouer avec un 400 et la liste des règles violées.

Rends variantes optionnel avec @IsOptional() (garde @IsArray() et @IsString({ each: true }) à côté). Vérifie qu’un produit créé sans ce champ est accepté, et qu’un produit créé avec passe toujours la validation.

Active whitelist: true et forbidNonWhitelisted: true. Envoie un POST /api/produits valide, avec un champ en plus qui n’existe pas dans ton DTO (par exemple "remise": 50). Vérifie qu’il est désormais rejeté, avec un message qui le nomme.

Envoie "variantes": ["S", 42, "L"] (un nombre glissé au milieu des chaînes). Vérifie que @IsString({ each: true }) le détecte et rejette la requête — l’option each: true s’applique à chaque élément du tableau, pas au tableau lui-même.

Pour vérifier ton travail : npm run test:partie-4 (dépôt d'exercices)