В экосистеме TypeScript и JavaScript при работе с DTO (Data Transfer Objects) часто возникает необходимость контролировать не только валидацию входящих данных, но и их форму при преобразовании объектов между слоями приложения. Для этого используется связка двух библиотек: class-validator и class-transformer. Первая отвечает за проверку данных, вторая — за преобразование экземпляров классов в обычные объекты и обратно.
Декоратор @Exclude относится именно к class-transformer
и используется для исключения свойств из процесса сериализации или
десериализации. Его задача — управлять тем, какие поля попадут в
итоговый объект после выполнения plainToInstance или
instanceToPlain.
При преобразовании объекта экземпляра класса в plain-объект
(например, перед отправкой ответа API), class-transformer проходит по
всем свойствам и применяет правила трансформации. Если свойство помечено
@Exclude, оно исключается из результата.
import { Exclude } from 'class-transformer';
export class UserDto {
id: number;
email: string;
@Exclude()
password: string;
}
При преобразовании:
plainToInstance(UserDto, userEntity)
поле password будет удалено из итогового объекта.
@Exclude работает только в контексте class-transformer и
не влияет на исходный объект в памяти. Это означает:
Декоратор поддерживает тонкую настройку поведения через параметры.
@Exclude({ toPlainOnly: true })
password: string;
В этом случае поле будет скрыто при отправке наружу, но останется доступным при создании объекта из plain-данных.
@Exclude({ toClassOnly: true })
internalFlag: boolean;
Такое поведение используется реже, но может быть полезно при фильтрации входных данных.
@Exclude()
secretToken: string;
Поле исключается в обе стороны трансформации.
@Exclude часто применяется совместно с
@Expose, который выполняет обратную задачу — явно включает
свойства в трансформацию.
import { Exclude, Expose } from 'class-transformer';
export class ProductDto {
@Expose()
title: string;
@Expose()
price: number;
@Exclude()
internalCode: string;
}
При такой конфигурации можно построить модель, где видимыми считаются только явно отмеченные поля, а остальные игнорируются.
class-transformer поддерживает режим, при котором можно задать поведение «по умолчанию»:
{
excludeExtraneousValues: true
}
В этом режиме все поля, не помеченные @Expose,
автоматически исключаются. Тогда @Exclude становится
дополнительным инструментом точечной блокировки данных.
В архитектуре приложений на NestJS и аналогичных фреймворках DTO-классы часто служат границей между слоями. Исключение полей позволяет:
export class AccountDto {
id: number;
username: string;
@Exclude()
hashedPassword: string;
@Exclude({ toPlainOnly: true })
refreshToken: string;
}
Важно разграничивать роли библиотек:
@IsString,
@IsEmail, @MinLength);@Exclude, @Transform,
@Expose).@Exclude не выполняет валидацию и не влияет на неё
напрямую. Однако в реальных приложениях оба слоя работают
последовательно: сначала трансформация, затем проверка (или наоборот, в
зависимости от конфигурации пайплайна).
Исключение работает рекурсивно при условии, что вложенные объекты также являются экземплярами классов и имеют соответствующие декораторы.
export class ProfileDto {
bio: string;
@Exclude()
internalNotes: string;
}
export class UserDto {
name: string;
profile: ProfileDto;
}
При корректной трансформации поле internalNotes внутри
profile также будет исключено.
@Exclude работает только при использовании
class-transformer. Если объект создаётся как plain JavaScript object без
plainToInstance, декораторы не применяются.
const dto = {
...userInstance
};
В этом случае исключения не произойдёт, поскольку происходит прямое копирование свойств без участия class-transformer.
@Exclude не предотвращает попадание данных в систему. Он
лишь контролирует их представление после трансформации.
Типичная модель использования включает разделение:
@Exclude.export class UserResponseDto {
id: number;
email: string;
@Exclude()
password: string;
@Exclude()
resetToken: string;
}
Такой подход снижает риск случайной утечки чувствительных данных при сериализации ответов API.