Introduction to class-validator
\n\nclass-validator is a powerful and popular library for data validation in TypeScript and JavaScript, built on decorators. It allows you to declaratively describe validation rules directly inside classes using annotations. This makes the code clean, readable, and easily maintainable.
\n\nThe library is especially useful when developing server-side applications (e.g., on NestJS or Express), where you need to validate incoming requests, form data, configurations, and any other data structures. Instead of writing cumbersome if-else chains, you simply add decorators to class properties.
\n\nWhy use class-validator?
\n\n- \n
- Declarative: Validation rules are defined alongside the data, improving readability. \n
- Powerful set of validators: Includes dozens of built-in decorators for checking strings, numbers, dates, arrays, nested objects, and much more. \n
- Custom validators: Allows you to easily create your own rules. \n
- Integration with TypeScript: Full support for types and decorators. \n
- Asynchronous validation: Supports checks that require asynchronous operations (e.g., checking uniqueness in a database). \n
Installation
\n\nTo use class-validator, you need Node.js and npm/yarn. Install the library and required dependencies:
\n\nnpm install class-validator class-transformer reflect-metadata\n\nOr via yarn:
\n\nyarn add class-validator class-transformer reflect-metadata\n\nImportant: The reflect-metadata library is required for decorators to work. Make sure it is imported in your main file (e.g., index.ts or main.ts):
import 'reflect-metadata';\n\nAlso ensure that your tsconfig.json includes the following settings:
{\n "compilerOptions": {\n "experimentalDecorators": true,\n "emitDecoratorMetadata": true\n }\n}\n\nQuick Start
\n\nLet's create a simple user model and validate it.
\n\nimport 'reflect-metadata';\nimport { validate, IsString, IsEmail, MinLength } from 'class-validator';\nimport { plainToClass } from 'class-transformer';\n\nclass User {\n @IsString()\n @MinLength(3, { message: 'Name must be at least 3 characters long' })\n name: string;\n\n @IsEmail({}, { message: 'Invalid email' })\n email: string;\n\n constructor(name: string, email: string) {\n this.name = name;\n this.email = email;\n }\n}\n\nasync function main() {\n // Create an object with invalid data\n const userData = { name: 'Jo', email: 'not-an-email' };\n \n // Transform plain object into a class instance\n const user = plainToClass(User, userData);\n \n // Validate\n const errors = await validate(user);\n \n if (errors.length > 0) {\n console.log('Validation errors:', errors);\n errors.forEach(error => {\n console.log(`Field: ${error.property}`);\n for (const constraint in error.constraints) {\n console.log(` - ${error.constraints[constraint]}`);\n }\n });\n } else {\n console.log('Validation passed successfully!');\n }\n}\n\nmain();\n// Output:\n// Validation errors: [...]\n// Field: name\n// - Name must be at least 3 characters long\n// Field: email\n// - Invalid email\n\nMain Methods and Decorators
\n\n1. @IsString()
\nWhat it does: Checks if the value is a string.
\nParameters: Accepts an optional object with validation options (e.g., { message: '...' }).