Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
claude-dev-suite avatar

Class Validator

  • 40 installs
  • 27 repo stars
  • Updated July 17, 2026
  • claude-dev-suite/claude-dev-suite

Validate TypeScript DTOs with class-validator decorators, the standard validation approach in NestJS via ValidationPipe.

About

Reference for class-validator covering decorator-based DTO validation, class-transformer integration, and the NestJS ValidationPipe. A developer uses it when validating request DTOs in NestJS or class-based TypeScript apps.

  • Decorator-based DTO validation
  • NestJS ValidationPipe integration

Class Validator by the numbers

  • 40 all-time installs (skills.sh)
  • Ranked #3,286 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
  • Data as of Jul 29, 2026 (Skillselion catalog sync)
npx skills add https://github.com/claude-dev-suite/claude-dev-suite --skill class-validator

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs40
repo stars27
Last updatedJuly 17, 2026
Repositoryclaude-dev-suite/claude-dev-suite

What it does

Validate TypeScript DTOs with class-validator decorators, the standard validation approach in NestJS via ValidationPipe.

Files

SKILL.mdMarkdownGitHub ↗

Class-validator - Quick Reference

Full Reference: See advanced.md for custom validators, cross-field validation, validation groups, error formatting, and class-transformer integration.
Deep Knowledge: Use mcp__documentation__fetch_docs with technology: class-validator for comprehensive documentation.

Setup

npm install class-validator class-transformer
// tsconfig.json
{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

Basic Usage

import {
  validate,
  IsString,
  IsEmail,
  IsInt,
  Min,
  Max,
  Length,
  IsOptional,
} from 'class-validator';
import { plainToInstance } from 'class-transformer';

class CreateUserDto {
  @IsString()
  @Length(2, 50)
  name: string;

  @IsEmail()
  email: string;

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

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

// Validate
async function validateUser(data: unknown) {
  const user = plainToInstance(CreateUserDto, data);
  const errors = await validate(user);

  if (errors.length > 0) {
    throw new Error(errors.map((e) => Object.values(e.constraints || {})).flat().join(', '));
  }

  return user;
}

Common Decorators

String Validators

import {
  IsString, IsNotEmpty, Length, MinLength, MaxLength,
  Matches, IsUUID, IsEmail, IsUrl, IsIP,
} from 'class-validator';

class StringValidationDto {
  @IsString()
  @IsNotEmpty()
  required: string;

  @Length(5, 20)
  username: string;

  @MinLength(8)
  @Matches(/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$/, {
    message: 'Password must contain letters and numbers',
  })
  password: string;

  @IsEmail()
  email: string;

  @IsUrl({ require_protocol: true })
  website: string;

  @IsUUID('4')
  id: string;
}

Number Validators

import { IsNumber, IsInt, IsPositive, Min, Max, IsDivisibleBy } from 'class-validator';

class NumberValidationDto {
  @IsNumber()
  decimal: number;

  @IsInt()
  integer: number;

  @IsPositive()
  positive: number;

  @Min(0)
  @Max(100)
  percentage: number;
}

Date Validators

import { IsDate, MinDate, MaxDate, IsISO8601 } from 'class-validator';
import { Type } from 'class-transformer';

class DateValidationDto {
  @IsDate()
  @Type(() => Date)
  date: Date;

  @MinDate(new Date('2020-01-01'))
  @Type(() => Date)
  afterDate: Date;

  @IsISO8601()
  isoString: string;
}

Array Validators

import {
  IsArray, ArrayMinSize, ArrayMaxSize, ArrayUnique,
  ArrayNotEmpty, ValidateNested,
} from 'class-validator';
import { Type } from 'class-transformer';

class ItemDto {
  @IsString()
  name: string;
}

class ArrayValidationDto {
  @IsArray()
  @ArrayNotEmpty()
  @ArrayMinSize(1)
  @ArrayMaxSize(10)
  @IsString({ each: true })  // Validate each item
  tags: string[];

  @IsArray()
  @ValidateNested({ each: true })
  @Type(() => ItemDto)
  items: ItemDto[];
}

Nested Object Validation

import { IsObject, ValidateNested } from 'class-validator';
import { Type } from 'class-transformer';

class AddressDto {
  @IsString()
  street: string;

  @IsString()
  city: string;
}

class UserWithAddressDto {
  @IsString()
  name: string;

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

Other Validators

import {
  IsBoolean, IsEnum, IsIn, IsOptional,
  IsCreditCard, IsPhoneNumber,
} from 'class-validator';

enum UserRole {
  ADMIN = 'admin',
  USER = 'user',
  GUEST = 'guest',
}

class MixedValidationDto {
  @IsBoolean()
  active: boolean;

  @IsEnum(UserRole)
  role: UserRole;

  @IsIn(['draft', 'published', 'archived'])
  status: string;

  @IsOptional()
  @IsCreditCard()
  creditCard?: string;
}

NestJS Integration

// main.ts
import { ValidationPipe } from '@nestjs/common';

app.useGlobalPipes(
  new ValidationPipe({
    whitelist: true,           // Strip non-decorated properties
    forbidNonWhitelisted: true, // Throw on unknown properties
    transform: true,            // Auto-transform payloads to DTO instances
    transformOptions: {
      enableImplicitConversion: true,
    },
  })
);
// users.controller.ts
@Controller('users')
export class UsersController {
  @Post()
  create(@Body() createUserDto: CreateUserDto) {
    // createUserDto is already validated and transformed
    return this.usersService.create(createUserDto);
  }

  @Get()
  findAll(@Query() query: PaginationQueryDto) {
    // Query params also validated
    return this.usersService.findAll(query);
  }

  @Get(':id')
  findOne(@Param('id', ParseUUIDPipe) id: string) {
    return this.usersService.findOne(id);
  }
}

Partial DTOs (for updates)

import { PartialType, OmitType, PickType, IntersectionType } from '@nestjs/mapped-types';

// All fields optional
export class UpdateUserDto extends PartialType(CreateUserDto) {}

// Omit specific fields
export class CreateUserWithoutPasswordDto extends OmitType(CreateUserDto, ['password']) {}

// Pick specific fields
export class LoginDto extends PickType(CreateUserDto, ['email', 'password']) {}

// Combine DTOs
export class ExtendedUserDto extends IntersectionType(CreateUserDto, AdditionalFieldsDto) {}

Custom Validator (Basic)

import {
  registerDecorator,
  ValidationOptions,
  ValidatorConstraint,
  ValidatorConstraintInterface,
  ValidationArguments,
} from 'class-validator';

@ValidatorConstraint({ async: false })
export class IsStrongPasswordConstraint implements ValidatorConstraintInterface {
  validate(password: string, args: ValidationArguments) {
    const hasUppercase = /[A-Z]/.test(password);
    const hasLowercase = /[a-z]/.test(password);
    const hasNumber = /\d/.test(password);
    const minLength = password.length >= 8;

    return hasUppercase && hasLowercase && hasNumber && minLength;
  }

  defaultMessage(args: ValidationArguments) {
    return 'Password must contain uppercase, lowercase, and number';
  }
}

export function IsStrongPassword(validationOptions?: ValidationOptions) {
  return function (object: Object, propertyName: string) {
    registerDecorator({
      target: object.constructor,
      propertyName: propertyName,
      options: validationOptions,
      constraints: [],
      validator: IsStrongPasswordConstraint,
    });
  };
}

// Usage
class RegisterDto {
  @IsStrongPassword()
  password: string;
}

When NOT to Use This Skill

  • Client-side validation - Use Zod with React Hook Form
  • Non-NestJS backends - Zod is more framework-agnostic
  • Functional programming patterns - Decorators require classes
  • Simple validation - Zod has simpler API

Comparison: class-validator vs Zod

Featureclass-validatorZod
StyleDecoratorsFunctional
FrameworkNestJS standardFramework agnostic
Transformclass-transformerBuilt-in
Bundle sizeLargerSmaller
Type inferenceManualAutomatic

Anti-Patterns

Anti-PatternWhy It's BadCorrect Approach
Missing @Type() decoratorNested validation failsUse @Type() for nested objects
No whitelist in ValidationPipeAccepts unknown propertiesSet whitelist: true
Using any in DTOsBypasses validationUse proper types
Manual validation in controllerCode duplicationUse ValidationPipe globally
Missing experimentalDecoratorsDecorators don't workEnable in tsconfig.json
Not using class-transformerPlain objects not validatedUse plainToInstance()

Quick Troubleshooting

IssueCauseSolution
Decorators not workingtsconfig misconfiguredEnable experimentalDecorators: true
Nested validation failsMissing @Type()Add @Type(() => NestedClass)
Validation not runningValidationPipe not setAdd ValidationPipe globally in main.ts
Unknown properties acceptedNo whitelistSet whitelist: true in ValidationPipe
Transform not workingMissing transform optionSet transform: true in ValidationPipe
Async validators failWrong setupUse async: true in @ValidatorConstraint

Checklist

  • [ ] tsconfig with decorators enabled
  • [ ] class-transformer for nested/transform
  • [ ] Global ValidationPipe in NestJS
  • [ ] whitelist and forbidNonWhitelisted
  • [ ] Custom validators for specific logic
  • [ ] Error formatting for API responses

Reference

Deep Knowledge: Use mcp__documentation__fetch_docs with technology: class-validator
- class-validator GitHub

Related skills

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.