typescript 51 lines · 8 steps

How DTO validation works in NestJS

A decorated DTO class plus a global ValidationPipe turns untrusted request bodies into validated, typed objects.

Explained by highlit
1import { IsEmail, IsEnum, IsInt, IsOptional, IsString, Length, Max, Min } from 'class-validator';
2import { Type } from 'class-transformer';
3import { Body, Controller, Post } from '@nestjs/common';
4 
5enum UserRole {
6 Admin = 'admin',
7 Member = 'member',
8 Viewer = 'viewer',
9}
10 
11export class CreateUserDto {
12 @IsString()
13 @Length(2, 50)
14 name: string;
15 
16 @IsEmail()
17 email: string;
18 
19 @IsEnum(UserRole)
20 role: UserRole;
21 
22 @IsOptional()
23 @Type(() => Number)
24 @IsInt()
25 @Min(13)
26 @Max(120)
27 age?: number;
28}
29 
30@Controller('users')
31export class UsersController {
32 constructor(private readonly usersService: UsersService) {}
33 
34 @Post()
35 async create(@Body() dto: CreateUserDto) {
36 return this.usersService.create(dto);
37 }
38}
39 
40export async function bootstrap() {
41 const app = await NestFactory.create(AppModule);
42 app.useGlobalPipes(
43 new ValidationPipe({
44 whitelist: true,
45 forbidNonWhitelisted: true,
46 transform: true,
47 transformOptions: { enableImplicitConversion: false },
48 }),
49 );
50 await app.listen(3000);
51}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Decorators on DTO fields declare validation rules that the ValidationPipe enforces at the boundary.
  2. 2whitelist and forbidNonWhitelisted strip or reject any property your DTO doesn't explicitly allow.
  3. 3Pairing @Type with transform lets you coerce raw request values into the correct runtime types.

Related explainers

Share this explainer

Here's the card — post it anywhere.

How DTO validation works in NestJS — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code