Careeroza
Controllers, DTOs and Validation
Why are DTOs classes and not interfaces in NestJS?
Interfaces are erased at compile time. Classes exist at runtime, so they can carry class-validator decorators, be instantiated by class-transformer (transform: true), and be read by Swagger. ValidationPipe uses the parameter's class (from metadata) to know which rules to apply.
Explain ValidationPipe options whitelist, forbidNonWhitelisted and transform.
whitelist: true: strips properties that have no validation decorator (mass-assignment protection, e.g. a client sendingrole: "admin").forbidNonWhitelisted: true: rejects the request with 400 instead of silently stripping.transform: true: converts the plain body into a DTO instance and converts primitive params/query to the declared types ("7"to7), together with@Type(() => Number)orenableImplicitConversion.
How do you validate nested objects and arrays?
export class CreateOrderDto {
@ValidateNested({ each: true }) // validate every element
@Type(() => OrderItemDto) // tell class-transformer the element class
@ArrayMinSize(1)
items: OrderItemDto[];
@ValidateNested()
@Type(() => AddressDto)
address: AddressDto;
}Without @Type, the nested values stay plain objects and their decorators are never checked.
How do you create an UpdateDto without copying all fields?
Use mapped types: class UpdateProductDto extends PartialType(CreateProductDto) {}. They copy the properties and validation decorators and make them optional. PickType, OmitType and IntersectionType also exist. Import them from @nestjs/swagger if you use Swagger (so docs stay correct), otherwise from @nestjs/mapped-types.