Nested and Array DTO Validation
Validate nested objects and collections with @ValidateNested, @Type, and whitelist stripping.
Why Nested Validation Needs Help
NestJS pairs class-validator with class-transformer through the global ValidationPipe. For flat DTOs this works out of the box: decorators on each property run automatically.
But the moment a DTO contains another object or an array of objects, validation silently stops at the boundary. The validator sees a child property, but it does not know it is a class instance whose own decorators should run.
- A nested
addressobject is treated as an opaque value. - An
itemsarray is checked for being an array, but its elements are never validated.
This lesson shows how @ValidateNested, @Type, and whitelist stripping close those gaps.
The Problem in Code
Consider an order payload with a nested address. Adding @ValidateNested alone is not enough — the validator still needs the child to be an actual AddressDto instance, not a plain object.
Without @Type, class-transformer leaves address as a plain object, so the @IsString() on city never runs. Invalid data passes through unnoticed.
import { IsString, ValidateNested } from 'class-validator';
// AddressDto's own rules will NOT run yet
class AddressDto {
@IsString()
city: string;
}
export class CreateOrderDto {
@ValidateNested() // declares intent, but lacks a target type
address: AddressDto;
}