Контроллеры, DTO, ValidationPipe

↑ 6.2 NestJS · ← Предыдущая · → Следующая

По желанию~3 мин чтенияУровень: junior

Зачем это на собесе

Как принимаются и проверяются данные в Nest: DTO и class-validator.

Объяснение

export class CreateOrderDto {
  @IsString() @IsNotEmpty() @MaxLength(100) customer: string;
  @IsInt() @Min(1) @Max(1000) quantity: number;
  @IsEmail() email: string;
  @IsOptional() @IsEnum(Priority) priority?: Priority;
}
 
@Controller("orders")
export class OrdersController {
  constructor(private readonly orders: OrdersService) {}
 
  @Post()
  @HttpCode(201)
  create(@Body() dto: CreateOrderDto) { return this.orders.create(dto); }
 
  @Get(":id")
  find(@Param("id", ParseUUIDPipe) id: string) { return this.orders.find(id); }
 
  @Get()
  list(@Query() q: ListOrdersQuery) { return this.orders.list(q); }
}

Глобальная валидация:

app.useGlobalPipes(new ValidationPipe({
  whitelist: true,              // убрать поля, не описанные в DTO
  forbidNonWhitelisted: true,   // 400 при лишних полях
  transform: true,              // приводить типы (строка → число) и создавать экземпляры DTO
}));

DTO — классы, а не интерфейсы: интерфейсы стираются при компиляции, и декораторы class-validator работают только на классах. Альтернативы: Zod/Valibot с пайпом.

Нюансы и подводные камни

  • Без whitelist в объект попадают любые поля (mass assignment).
  • Вложенные объекты требуют @ValidateNested() и @Type(() => Nested).
  • Query-параметры приходят строками: нужен transform: true или ParseIntPipe.
  • DTO для ответа тоже нужны: не отдавайте сущности БД (ClassSerializerInterceptor).
  • Формат ошибок валидации стандартизируйте фильтром исключений.

Практика

  1. Опишите DTO создания и обновления (PartialType) заказа.
  2. Включите whitelist и проверьте лишние поля.
  3. Реализуйте валидацию вложенных позиций заказа.

Вопросы с ответами

Связанные темы