Как настроить валидацию с class-validator в NestJS?

MiddleNestJS · Backend·Обновлено 18 июля 2026
Коротко
Нужно установить пакеты class-validator и class-transformer, подключить глобальный ValidationPipe в main.ts, а затем использовать декораторы из class-validator в DTO-классах.

Настройка валидации с class-validator в NestJS

Установка зависимостей

Для работы валидации необходимо установить два пакета:

npm install class-validator class-transformer

class-validator предоставляет декораторы для описания правил валидации, а class-transformer — преобразует plain-объекты запроса в экземпляры DTO-классов, без чего декораторы не работают.

Подключение ValidationPipe

Globalный пайп подключается в main.ts через app.useGlobalPipes():

// main.ts
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(
  new ValidationPipe({
    whitelist: true,        // удаляет поля, не описанные в DTO
    forbidNonWhitelisted: true, // выбрасывает ошибку при лишних полях
    transform: true,        // преобразует входные данные к типам DTO
  }),
);

Опция transform: true критична — без неё class-transformer не создаёт экземпляр класса и декораторы class-validator не срабатывают.

Создание DTO с декораторами

// create-user.dto.ts
import { IsString, IsEmail, IsInt, Min, Max, IsOptional } from 'class-validator';

export class CreateUserDto {
  @IsString()
  name: string;

  @IsEmail()
  email: string;

  @IsInt()
  @Min(18)
  @Max(120)
  age: number;

  @IsOptional()
  @IsString()
  bio?: string;
}

Использование DTO в контроллере

@Post('users')
createUser(@Body() dto: CreateUserDto) {
  // если валидация не прошла — NestJS автоматически вернёт 400 Bad Request
  return this.usersService.create(dto);
}

Вложенная валидация

Для объектов внутри DTO нужен дополнительный декоратор @ValidateNested и @Type:

import { ValidateNested } from 'class-validator';
import { Type } from 'class-transformer';

export class CreateOrderDto {
  @ValidateNested()
  @Type(() => AddressDto)  // указываем класс для трансформации
  address: AddressDto;
}

Кастомные сообщения об ошибках

@IsString({ message: 'Имя должно быть строкой' })
@MinLength(2, { message: 'Имя не может быть короче $constraint1 символов' })
name: string;

Альтернатива: pipe на уровне маршрута

Если глобальный пайп не подходит, его можно применить точечно:

@Post()
createUser(
  @Body(new ValidationPipe()) dto: CreateUserDto
) { ... }

Частые проблемы

  • Без transform: true валидация не работает, потому что NestJS передаёт plain object, а не экземпляр класса.
  • Без @Type(() => NestedDto) вложенные объекты не трансформируются и @ValidateNested игнорируется.

Что хочет услышать интервьюер

Знание необходимых пакетов: class-validator и class-transformer — оба обязательны

Понимание роли ValidationPipe и важности опции transform: true

Умение создавать DTO-классы с декораторами валидации

Знание whitelist и forbidNonWhitelisted для защиты от лишних полей

Понимание как обрабатывать вложенные объекты через @ValidateNested и @Type

Пример: main.ts — подключение глобального ValidationPipe

import { NestFactory } from '@nestjs/core';
import { ValidationPipe } from '@nestjs/common';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

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

  await app.listen(3000);
}
bootstrap();

Пример: create-user.dto.ts — DTO с декораторами валидации

import {
  IsString,
  IsEmail,
  IsInt,
  Min,
  Max,
  IsOptional,
  MinLength,
} from 'class-validator';

export class CreateUserDto {
  @IsString()
  @MinLength(2, { message: 'Имя слишком короткое' })
  name: string;

  @IsEmail({}, { message: 'Некорректный email' })
  email: string;

  @IsInt()
  @Min(18)
  @Max(120)
  age: number;

  @IsOptional()
  @IsString()
  bio?: string;
}

Пример: Вложенная валидация с @ValidateNested

import { ValidateNested, IsString } from 'class-validator';
import { Type } from 'class-transformer';

class AddressDto {
  @IsString()
  city: string;

  @IsString()
  street: string;
}

export class CreateOrderDto {
  @ValidateNested()
  @Type(() => AddressDto) // обязательно для трансформации
  address: AddressDto;
}

Типичные ошибки

Забывают установить class-transformer или не указывают transform: true — декораторы молча не срабатывают

Подключают ValidationPipe только глобально через useGlobalPipes, но используют модульный подход — pipe, добавленный вне модуля, не подхватывает провайдеры

Не используют @ValidateNested + @Type для вложенных DTO — валидация вложенных объектов не выполняется

Используют интерфейсы вместо классов для DTO — декораторы работают только с классами

Включают whitelist: true, но не понимают, что это изменяет тело запроса (удаляет лишние поля)

Лучшие курсы по теме

изображение курса

Docker и Ansible

Антон Ларичев
AI-тренажерыAI-тренажеры
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Node.js с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Nest.js с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.6
3 999 ₽ 6 990 ₽
Подробнее