Validating DTOs with class-validator

Decorate DTO properties with class-validator rules like @IsString and @IsEmail.

Syntax@IsEmail() email: string;

class-validator provides decorators you attach to DTO properties. Combined with the ValidationPipe, they enforce rules on incoming data.

Common decorators

DecoratorChecks
@IsString()Value is a string
@IsEmail()Valid email format
@IsInt()Whole number
@Min(n) / @Max(n)Numeric range
@IsOptional()Property may be omitted

If any rule fails, the ValidationPipe throws a 400 with a list of messages before your handler runs.

Example

Example Β· typescript
import { IsString, IsEmail, IsInt, Min } from 'class-validator';

export class CreateUserDto {
  @IsString()
  name: string;

  @IsEmail()
  email: string;

  @IsInt()
  @Min(0)
  age: number;
}

When to use it

  • A developer decorates an email field with @IsEmail() so the ValidationPipe rejects invalid email formats before the service even receives the data.
  • A team uses @IsOptional() combined with @MinLength(8) on a password field so the field is not required but must meet length rules if provided.
  • An engineer uses @ValidateNested() with @Type(() => AddressDto) to validate a nested object inside a parent DTO.

More examples

DTO with common validators

Shows a DTO with string, email, integer range, and optional string validators in a single class.

Example Β· ts
import { IsString, IsEmail, IsInt, Min, Max, IsOptional } from 'class-validator';

export class CreateUserDto {
  @IsString()
  name: string;

  @IsEmail()
  email: string;

  @IsInt()
  @Min(18)
  @Max(120)
  age: number;

  @IsOptional()
  @IsString()
  bio?: string;
}

Nested object validation

Uses @ValidateNested with @Type to recursively validate a nested DTO object inside a parent DTO.

Example Β· ts
import { ValidateNested, IsString } from 'class-validator';
import { Type } from 'class-transformer';

export class AddressDto {
  @IsString() street: string;
  @IsString() city: string;
}

export class CreateOrderDto {
  @ValidateNested()
  @Type(() => AddressDto)
  shippingAddress: AddressDto;
}

Custom error messages

Passes a message option to each decorator so validation errors return human-readable messages instead of defaults.

Example Β· ts
import { IsString, MinLength, IsEmail } from 'class-validator';

export class RegisterDto {
  @IsString({ message: 'Username must be text' })
  @MinLength(3, { message: 'Username too short β€” min 3 chars' })
  username: string;

  @IsEmail({}, { message: 'Please provide a valid email address' })
  email: string;
}

Discussion

  • Be the first to comment on this lesson.