class-validator
class-validator is a third-party library that allows you to use decorator-based validation on your TypeScript classes. It is the de-facto standard for validation in NestJS.
Overview
Instead of writing imperative validation logic (if (typeof user.age !== 'number')), class-validator allows you to declare validation rules directly on the properties of your DTO (Data Transfer Object) classes using decorators.
NestJS’s built-in ValidationPipe automatically hooks into class-validator to enforce these rules on incoming HTTP requests.
Key Concepts
- Decorators: The core mechanism. You apply decorators like
@IsString(),@IsOptional(), or@Min()to class properties. - Validation Messages: Every decorator generates a default, human-readable error message, which you can easily customize.
- Nested Validation: You can validate complex JSON structures (objects within objects, arrays of objects) using the
@ValidateNested()decorator.
Code Examples
Basic Validation Rules
Here is a DTO demonstrating some of the most common validation decorators.
import {
IsString,
IsInt,
Min,
Max,
IsEmail,
IsOptional,
IsEnum
} from 'class-validator';
enum UserRole {
ADMIN = 'admin',
USER = 'user',
}
export class UpdateUserDto {
@IsString()
@IsOptional() // This field doesn't have to be provided, but if it is, it must be a string.
name?: string;
@IsEmail({}, { message: 'Please provide a valid corporate email address' })
email: string; // Required by default!
@IsInt()
@Min(18)
@Max(120)
age: number;
@IsEnum(UserRole)
role: UserRole;
}
Validating Arrays and Nested Objects
Validating an array of strings is easy (using each: true). Validating an array of other objects requires combining class-validator with class-transformer (using @Type).
import { IsString, IsArray, ValidateNested } from 'class-validator';
import { Type } from 'class-transformer';
class AddressDto {
@IsString()
street: string;
@IsString()
city: string;
}
export class CreateUserDto {
// Simple array of strings
@IsArray()
@IsString({ each: true })
tags: string[];
// Array of complex objects
@IsArray()
@ValidateNested({ each: true }) // Tell class-validator to validate the children
@Type(() => AddressDto) // Tell class-transformer which class to instantiate
addresses: AddressDto[];
}
Best Practices
- Custom Validators: If the built-in decorators aren’t enough (e.g., you need to check if an email already exists in the database), you can write custom
@IsUnique()decorators by implementing theValidatorConstraintInterface. - Install both libraries: To use
class-validatorin NestJS, you almost always need to installclass-transformeralongside it:npm i class-validator class-transformer. - IsOptional() vs default values: If a field is not required, use
@IsOptional(). Do not rely on TypeScript’s?operator alone, as theValidationPipeignores TypeScript types at runtime.