NestJS course Β· Module 10: Data Validation

Gate Guard - Introduction to Data Validation

3 min read
In this lesson4

Salve, legionary! You have reached one of the most important locations in our Empire - the Main Gate (Porta Praetoria). Everyone who wants to enter the city must pass through the guards' checkpoint. Similarly, every HTTP request that reaches our server should be thoroughly checked before it reaches the business logic.

Data validation is the process of verifying whether incoming data from users is correct, safe, and meets expectations. Without validation, our server is like an open gate - anyone can enter with anything.

Why Is Validation Essential?

Imagine a legionary approaching the gate and claiming to be a senator. The guard checks:

  • Does he have a proper identity document? (required fields)
  • Is the document not forged? (correct format)
  • Do the details match? (business rules)

In the NestJS world, we deal with an analogous situation:

1// WITHOUT validation - gate wide open!
2@Post('legionaries')
3createLegionary(@Body() body: any) {
4  // Someone can send anything!
5  // { name: 12345, rank: null, age: "cat" }
6  return this.service.create(body);
7}
8
9// WITH validation - guards on duty!
10@Post('legionaries')
11createLegionary(@Body() dto: CreateLegionaryDto) {
12  // Data is verified before it reaches here
13  // name must be a string, rank must exist, age must be a number
14  return this.service.create(dto);
15}

What Is a DTO?

DTO (Data Transfer Object) is like an official imperial document - it defines exactly which fields should be present and what types they should be. In NestJS, we create DTO classes that describe the shape of input data:

1// DTO is like an imperial form
2export class CreateLegionaryDto {
3  name: string;     // Legionary's name
4  rank: string;     // Rank
5  age: number;      // Age
6  legio: string;    // Legion name
7}

Validation Tools in NestJS

NestJS offers three main tools to protect our gates:

  1. class-validator - a library of decorators for defining validation rules
  2. class-transformer - a tool for data transformation (type conversion, field exclusion)
  3. ValidationPipe - a built-in NestJS pipe that automatically runs validation
1// Installing gate guards
2// npm install class-validator class-transformer

How Does It All Work Together?

The entire validation process in NestJS works as follows:

1// 1. HTTP request arrives at the server
2// POST /legionaries { name: "Marcus", age: 25 }
3
4// 2. ValidationPipe intercepts the data
5// ValidationPipe runs class-transformer (type conversion)
6// Then class-validator (rule checking)
7
8// 3. If data is valid β†’ passes to the controller
9// If data is invalid β†’ returns 400 Bad Request error

Without these tools, we would have to manually check every field in every endpoint - it's as if you asked every centurion to personally verify documents instead of having trained gate guards.

In the following lessons, you will learn about each of these tools in detail. Get ready, because the gate guard shows no mercy to invalid data!

Code for this lesson: src/validation-intro.ts
1// Imperium Gate Guard - Introduction to Validation
2// Comparison of endpoints with and without validation
3
4import { Controller, Post, Body } from '@nestjs/common';
5
6// ================================
7// WITHOUT VALIDATION - Open gate!
8// ================================
9
10interface RawLegionary {
11  name: any;
12  rank: any;
13  age: any;
14}
15
16@Controller('unsafe')
17class UnsafeController {
18  @Post()
19  create(@Body() body: RawLegionary) {
20    // Someone could send: { name: 123, rank: null, age: "cat" }
21    console.log('Received data (without validation):', body);
22    return body;
23  }
24}
25
26// ================================
27// WITH VALIDATION - Guarded gate!
28// ================================
29
30// DTO defines the shape of data
31class CreateLegionaryDto {
32  name: string;   // Must be a string
33  rank: string;   // Must be a string
34  age: number;    // Must be a number
35}
36
37@Controller('safe')
38class SafeController {
39  @Post()
40  create(@Body() dto: CreateLegionaryDto) {
41    // Data is validated before it gets here
42    console.log('Received data (with validation):', dto);
43    return dto;
44  }
45}
46
47console.log('Without validation: anyone can enter with anything');
48console.log('With validation: gate guard checks documents');
49console.log('DTO = official imperial form');
50

Spotted a mistake in this lesson?

Check yourself

Answer the questions from this lesson. Pick an answer to see right away whether it is correct.

  1. 1. What is data validation in the context of a server application?

  2. 2. What is a DTO (Data Transfer Object) in NestJS?

These are 2 of 3 questions for this lesson. Solve the rest in the game.

Hands-on tasks in the game

  • Code editor

    Add @IsString, @IsNotEmpty, and @IsNumber decorators to the CreateGladiatorDto class

  • Click in order

    Arrange the steps of the HTTP request validation process in NestJS in the correct order:

Useful articles