Механизм групп в библиотеке class-validator позволяет разделять правила валидации по контекстам использования одной и той же модели данных. Это особенно важно в ситуациях, где структура данных едина, но требования к обязательности и допустимости значений различаются в зависимости от операции.
Группы определяются строковыми идентификаторами и применяются как на уровне декораторов, так и на уровне запуска процесса валидации.
Каждое правило валидации может быть привязано к одной или нескольким группам. Если группа не указана, правило относится к группе по умолчанию.
import { IsString, IsEmail, IsOptional } from 'class-validator';
class UserDto {
@IsString({ groups: ['create'] })
name: string;
@IsEmail()
email: string;
@IsOptional({ groups: ['update'] })
password?: string;
}
В данном примере:
name проверяется только при созданииemail проверяется всегда (принадлежит
default-группе)password становится опциональным при обновленииГруппы активируются через параметры функций validate или
validateOrReject.
import { validate } from 'class-validator';
const dto = new UserDto();
validate(dto, {
groups: ['create'],
});
При указании группы create будут активированы только те
правила, которые явно с ней связаны, а также правила без указания группы
(default).
Наиболее распространённый паттерн использования групп — разделение логики создания и обновления сущности.
import { IsString, IsOptional, IsInt } from 'class-validator';
class ProductDto {
@IsString({ groups: ['create'] })
title: string;
@IsString({ groups: ['create', 'update'] })
description: string;
@IsInt({ groups: ['update'] })
id: number;
@IsOptional({ groups: ['update'] })
slug?: string;
}
Поведение:
create: проверяются title и
descriptionupdate: проверяются description,
id, slugТакой подход исключает необходимость создания отдельных DTO-классов для каждой операции.
Один класс может поддерживать несколько независимых сценариев.
class OrderDto {
@IsString({ groups: ['draft', 'submit'] })
comment: string;
@IsInt({ groups: ['submit'] })
paymentId: number;
@IsOptional({ groups: ['draft'] })
tempNote?: string;
}
Запуск с несколькими группами:
validate(order, {
groups: ['draft', 'submit'],
});
Если активируются сразу две группы, правила объединяются логически через объединение множеств.
Правила без указания groups относятся к default-группе и
активируются всегда, если не используется строгое разделение.
class AccountDto {
@IsEmail()
email: string;
@IsString({ groups: ['admin'] })
role: string;
}
Здесь:
email проверяется всегдаrole — только при группе adminГруппы часто комбинируются с условной валидацией для построения сложных сценариев.
import { ValidateIf, IsString } from 'class-validator';
class ProfileDto {
@ValidateIf((obj, value) => obj.type === 'full')
@IsString()
biography: string;
@IsString({ groups: ['full'] })
details: string;
}
Комбинация подходов позволяет:
ValidateIfПри использовании вложенных объектов группы передаются через вызов валидации и распространяются на вложенные структуры.
import { ValidateNested } from 'class-validator';
import { Type } from 'class-transformer';
class AddressDto {
@IsString({ groups: ['create'] })
city: string;
}
class UserDto {
@ValidateNested()
@Type(() => AddressDto)
address: AddressDto;
}
validate(user, { groups: ['create'] });
Вложенные объекты также получают контекст группы, что позволяет синхронизировать правила между уровнями модели.
Группы позволяют строить гибкие модели, где один и тот же класс используется в различных бизнес-процессах.
validate(data, { groups: ['registration'] });
validate(data, { groups: ['profile_update'] });
validate(data, { groups: ['admin_override'] });
Каждая группа может представлять отдельный сценарий:
В реальных моделях часто комбинируются строгие и контекстные ограничения.
class SessionDto {
@IsString()
token: string;
@IsOptional({ groups: ['refresh'] })
refreshToken?: string;
@IsString({ groups: ['login'] })
password: string;
}
Такой подход позволяет:
Если при валидации не указана опция groups, используются
только:
validate(dto); // активируется default-поведение
При строгой архитектуре часто применяется обязательное указание групп для всех сценариев, чтобы избежать случайного применения лишних правил.
Использование групп позволяет отказаться от множества отдельных классов DTO и заменить их одной моделью с вариативными правилами.
Типовая структура:
createupdatelistfilteradminКаждая группа описывает отдельный контекст данных, а декораторы становятся декларативным способом описания бизнес-логики валидации.
При увеличении количества сценариев группы начинают выступать как слой конфигурации над моделью данных. Это позволяет:
validate(payload, {
groups: ['admin', 'update'],
});
В таких случаях активируется пересечение правил нескольких сценариев, формируя итоговую схему проверки на лету.