What it is
class-validator validates objects using decorators on class properties, and is the validation layer built into NestJS.
Decorate class properties with constraints and call validate(). Because decorators need a runtime class, this cannot work with interfaces or type aliases.
Installation
npm install class-validator class-transformerGetting started
The smallest useful thing you can do with it, and what each part means.
typescript
import { IsEmail, IsInt, Min, Max, IsOptional, Length } from 'class-validator';
export class CreateUserDto {
@IsEmail()
email: string;
@IsInt() @Min(13) @Max(130)
age: number;
@IsOptional() @Length(0, 500)
bio?: string;
}
const errors = await validate(dto);
if (errors.length) {
const messages = errors.flatMap((e) => Object.values(e.constraints ?? {}));
throw new BadRequestException(messages);
}Advanced usage
Where the library earns its place over a simpler alternative.
typescript
import { plainToInstance } from 'class-transformer';
class Address {
@Length(1, 100) street: string;
}
class User {
@ValidateNested() @Type(() => Address)
address: Address;
@ValidateNested({ each: true }) @Type(() => Address)
previous: Address[];
}
// JSON.parse gives a plain object; decorators need a real instance.
const user = plainToInstance(User, JSON.parse(body));
const errors = await validate(user, { whitelist: true });Errors and fixes
The failures you are most likely to hit, and what actually resolves them.
- Validation always passes
- The object is a plain object, not a class instance. Convert it with plainToInstance.
- Reflect.getMetadata is not a function
- import 'reflect-metadata' once at the application entry point, before anything else.
Best practices
- Always convert with plainToInstance first; validating a plain object silently passes.
- Add @ValidateNested and @Type for nested structures — they are not traversed by default.
- Use whitelist: true to strip unknown properties.
- Prefer Zod for new non-Nest projects; it needs no decorators or reflect-metadata.
Background
Why it exists, and what it was reacting to.
It brought the annotation-driven validation style familiar from Java's Bean Validation to TypeScript, which is why it pairs naturally with the decorator-heavy NestJS architecture.
