В библиотеке class-validator параметр
groups используется для условного применения правил
валидации к различным сценариям работы с одной и той же моделью данных.
Он позволяет разделять наборы проверок внутри одного класса, формируя
логические группы правил, которые активируются только при явно указанной
группе во время выполнения валидации.
Группы валидации представляют собой механизм, позволяющий назначать отдельные правила проверки для разных контекстов использования объекта.
Каждый декоратор валидатора может принимать параметр:
groups: string[]Если группа указана у декоратора, правило будет применяться только тогда, когда при вызове функции валидации передана соответствующая группа.
Если группы не указаны ни у одного декоратора, такие правила
относятся к группе по умолчанию и выполняются всегда
(при отсутствии ограничения через groups в вызове
валидации).
Определение правил с группами выполняется через декораторы свойств класса:
import { IsEmail, IsNotEmpty, Length } from 'class-validator';
export class UserDto {
@IsEmail({}, { groups: ['create'] })
email: string;
@IsNotEmpty({ groups: ['create', 'update'] })
name: string;
@Length(6, 20, { groups: ['create'] })
password: string;
}
В этом примере:
email проверяется только при созданииname проверяется при создании и обновленииpassword проверяется только при созданииЧтобы активировать конкретную группу правил, используется параметр
groups в функции validate или
validateOrReject:
import { validate } from 'class-validator';
const dto = new UserDto();
dto.email = 'test@mail.com';
validate(dto, { groups: ['create'] });
При указании groups: ['create'] будут применены только
те валидаторы, которые помечены этой группой.
Если валидация выполняется без параметра groups,
библиотека применяет следующие правила:
groupsvalidate(dto);
В этом случае свойства, ограниченные группами, не участвуют в проверке.
Один валидатор может принадлежать нескольким группам одновременно:
@IsNotEmpty({ groups: ['create', 'update', 'admin'] })
username: string;
При вызове:
validate(dto, { groups: ['update'] });
валидатор будет активирован, поскольку update входит в
список групп.
Наиболее распространённый сценарий использования групп — разделение логики создания и обновления сущности.
export class ProductDto {
@IsNotEmpty({ groups: ['create'] })
title: string;
@IsOptional({ groups: ['update'] })
@IsNotEmpty({ groups: ['create'] })
description: string;
@IsNumber({}, { groups: ['create'] })
price: number;
}
Логика:
@ValidateNested и вложенными объектамиГруппы работают и с вложенной валидацией, но требуют явного указания:
import { ValidateNested } from 'class-validator';
import { Type } from 'class-transformer';
class AddressDto {
@IsNotEmpty({ groups: ['create'] })
city: string;
}
class UserDto {
@ValidateNested({ groups: ['create'] })
@Type(() => AddressDto)
address: AddressDto;
}
Без указания групп на уровне ValidateNested вложенные
проверки могут быть пропущены при использовании групповой
фильтрации.
@IsOptionalКомбинация groups и @IsOptional требует
аккуратности, так как поведение зависит от активной группы.
@IsOptional({ groups: ['update'] })
@IsString({ groups: ['update'] })
nickname?: string;
В сценарии обновления поле может отсутствовать и не вызывать ошибку, но при наличии будет проверено как строка.
При наличии группового ограничения:
groups игнорируются при указании
groups валидации@IsNotEmpty()
@IsEmail({ groups: ['create'] })
email: string;
Поведение:
groups → срабатывает IsNotEmptygroups: ['create'] → срабатывает
IsEmail, IsNotEmpty игнорируетсяОдин объект может одновременно удовлетворять нескольким сценариям, если группы пересекаются:
validate(dto, { groups: ['create', 'admin'] });
В этом случае активируются все валидаторы, принадлежащие любой из указанных групп.
class BaseUserDto {
@IsNotEmpty({ groups: ['create', 'update'] })
username: string;
}
class CreateUserDto extends BaseUserDto {
@IsEmail({ groups: ['create'] })
email: string;
}
class UpdateUserDto extends BaseUserDto {
@IsOptional({ groups: ['update'] })
email?: string;
}
Группы могут моделировать не только CRUD-сценарии, но и уровни доступа:
class DocumentDto {
@IsNotEmpty({ groups: ['user', 'admin'] })
title: string;
@IsString({ groups: ['admin'] })
internalNote: string;
}
validategroups: [] эквивалентен отсутствию
группыgroups передан в validate, но не указан в
декораторах — правила не активируютсяValidationPipe (NestJS)В архитектуре NestJS параметр групп часто передаётся через пайп:
new ValidationPipe({
groups: ['create'],
});
Это приводит к глобальной активации групповой логики для входящих DTO
без явного вызова validate.
Если валидатор принадлежит нескольким группам, а валидация вызвана с пересекающимся набором, правило считается активным:
@IsString({ groups: ['create', 'update'] })
name: string;
validate(dto, { groups: ['update'] });
Результат: валидатор применяется.
В больших моделях группировка часто применяется для:
class AccountDto {
@IsEmail({ groups: ['public'] })
email: string;
@IsString({ groups: ['admin'] })
internalId: string;
@IsBoolean({ groups: ['admin'] })
isBanned: boolean;
}
Если ни один валидатор не соответствует переданным группам:
Это поведение делает группы мощным инструментом, но требует строгого контроля конфигурации.