Real World Example

Checkout DTO with Nested Validation

An e-commerce checkout (Flipkart, Myntra, Meesho) sends a list of items and an address. Nested DTOs are validated with @ValidateNested + @Type.

src/orders/dto/create-order.dto.ts

import { Type } from 'class-transformer';
import { ArrayMaxSize, ArrayMinSize, IsEnum, IsInt, IsOptional, IsString, Length, Matches, Max, Min, ValidateNested } from 'class-validator';

export enum PaymentMethod { UPI = 'UPI', CARD = 'CARD', COD = 'COD' }

export class OrderItemDto {
  @IsInt() @Min(1) productId: number;
  @IsInt() @Min(1) @Max(10) quantity: number;
}

export class AddressDto {
  @IsString() @Length(5, 200) line1: string;
  @IsString() city: string;
  @Matches(/^[1-9][0-9]{5}$/, { message: 'pincode must be a valid 6-digit Indian PIN code' })
  pincode: string;
}

export class CreateOrderDto {
  @ValidateNested({ each: true })
  @Type(() => OrderItemDto)
  @ArrayMinSize(1)
  @ArrayMaxSize(50)
  items: OrderItemDto[];

  @ValidateNested()
  @Type(() => AddressDto)
  address: AddressDto;

  @IsEnum(PaymentMethod)
  paymentMethod: PaymentMethod;

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

Example

curl -X POST http://localhost:3000/orders -H "Content-Type: application/json" \
  -d '{"items":[{"productId":7,"quantity":20}],"address":{"line1":"12 MG Road","city":"Bengaluru","pincode":"056001"},"paymentMethod":"UPI"}'

Example output

{"message":["items.0.quantity must not be greater than 10","address.pincode must be a valid 6-digit Indian PIN code"],"error":"Bad Request","statusCode":400}