3 · Reliability and delivery · 30 MIN
Nest DTOs and validation pipes
DTO classes describe runtime validation through decorators.
A TypeScript interface disappears at runtime, so Nest’s decorator-based validation uses DTO classes. ValidationPipe applies those rules at the application boundary. whitelist removes properties without validation decorators, while forbidNonWhitelisted rejects those fields instead of silently stripping them. Decorators from class-validator enforce length and string type. Transformation and coercion should be deliberate: automatically converting arbitrary strings to numbers can obscure the accepted wire format.
Enable the pipe before listening.
Read the example
// npm install class-validator class-transformer
// preview.dto.ts
import {IsString,Length} from 'class-validator';
export class PreviewDto {@IsString() @Length(3,80) title!:string}
// preview.controller.ts
import {Body,Controller,Post} from '@nestjs/common';
import {PreviewDto} from './preview.dto';
@Controller('preview') export class PreviewController {@Post() preview(@Body() body:PreviewDto){return {preview:body.title}}}
// In main.ts, before await app.listen(...):
// import {ValidationPipe} from '@nestjs/common';
// app.useGlobalPipes(new ValidationPipe({whitelist:true,forbidNonWhitelisted:true}));Check the expected output
With the controller registered and pipe enabled, valid input succeeds and unknown or invalid fields return 400.
Your challenge
Add a bounded integer weeklyGoal field and test missing values, numeric strings and extra fields against an explicit wire contract.
Solution cost: O(f) validation for f fields, plus string-length work. time · O(f) DTO representation. space
Common trap
Decorators alone do nothing if the application never runs a validation pipe.
Study the project implementation
// npm install class-validator class-transformer
// preview.dto.ts
import {IsString,Length} from 'class-validator';
export class PreviewDto {@IsString() @Length(3,80) title!:string}
// preview.controller.ts
import {Body,Controller,Post} from '@nestjs/common';
import {PreviewDto} from './preview.dto';
@Controller('preview') export class PreviewController {@Post() preview(@Body() body:PreviewDto){return {preview:body.title}}}
// In main.ts, before await app.listen(...):
// import {ValidationPipe} from '@nestjs/common';
// app.useGlobalPipes(new ValidationPipe({whitelist:true,forbidNonWhitelisted:true}));Further reading: Official documentation
Next lesson: Project · Pagination with a stable contract →