Now that you know what validation is, it's time to learn about class-validator — a decorator library that turns ordinary DTO classes into real guard posts. Each decorator is like a separate guard specializing in a specific check.
1npm install class-validator class-transformerChecks whether the value is a string. It's like a guard verifying that the document is written on papyrus, not on stone:
1import { IsString } from 'class-validator';
2
3export class CreateLegionaryDto {
4 @IsString()
5 name: string; // "Marcus" ✅, 12345 ❌
6}Verifies whether the value is a number:
1import { IsNumber } from 'class-validator';
2
3export class CreateLegionaryDto {
4 @IsNumber()
5 age: number; // 25 ✅, "twenty five" ❌
6}Checks the validity of an email address format:
1import { IsEmail } from 'class-validator';
2
3export class CreateLegionaryDto {
4 @IsEmail()
5 cursusPublicus: string; // "marcus@roma.com" ✅, "marcus" ❌
6}Will not let empty values through — every field must have content:
1import { IsNotEmpty, IsString } from 'class-validator';
2
3export class CreateLegionaryDto {
4 @IsString()
5 @IsNotEmpty()
6 name: string; // "Marcus" ✅, "" ❌, null ❌
7}Control the minimum and maximum text length:
1import { MinLength, MaxLength, IsString } from 'class-validator';
2
3export class CreateLegionaryDto {
4 @IsString()
5 @MinLength(2)
6 @MaxLength(50)
7 name: string; // "Marcus" ✅, "M" ❌, "A".repeat(51) ❌
8}The real power of class-validator lies in combining multiple decorators on a single field. It's like several guards checking different aspects of one document:
1import {
2 IsString,
3 IsNotEmpty,
4 MinLength,
5 MaxLength,
6 IsNumber,
7 IsEmail,
8 Min,
9 Max,
10} from 'class-validator';
11
12export class CreateLegionaryDto {
13 @IsString()
14 @IsNotEmpty()
15 @MinLength(2)
16 @MaxLength(50)
17 name: string;
18
19 @IsString()
20 @IsNotEmpty()
21 rank: string;
22
23 @IsNumber()
24 @Min(16)
25 @Max(65)
26 age: number;
27
28 @IsEmail()
29 cursusPublicus: string;
30
31 @IsString()
32 @IsNotEmpty()
33 legio: string;
34}Each decorator accepts an optional parameter with an error message — so the guard can explain what's wrong:
1export class CreateLegionaryDto {
2 @IsString({ message: 'Name must be a text, legionary!' })
3 @IsNotEmpty({ message: 'Name cannot be empty!' })
4 @MinLength(2, { message: 'Name must have at least 2 characters!' })
5 name: string;
6
7 @IsNumber({}, { message: 'Age must be a number!' })
8 @Min(16, { message: 'You must be at least 16 years old to join the legion!' })
9 age: number;
10}Thanks to class-validator, you create a strong guard that automatically rejects invalid data before it reaches the business logic. In the next lesson, you will learn advanced decorators!