Class-validator — библиотека валидации данных для JavaScript и TypeScript
Class-validator представляет собой библиотеку, предназначенную для декларативной валидации объектов с использованием классов и декораторов. Основная идея заключается в том, чтобы описывать правила проверки данных прямо в модели, а не выносить их в отдельные функции или схемы. Такой подход делает код более структурированным и ближе к предметной области, особенно в проектах, где активно используются классы и TypeScript.
Библиотека активно применяется в экосистеме Node.js, особенно в связке с TypeScript и фреймворками, ориентированными на объектно-ориентированную модель. Её ключевая особенность — использование декораторов, позволяющих «прикреплять» правила валидации непосредственно к свойствам классов.
В основе class-validator лежит идея отражения метаданных о свойствах
классов и последующей их проверки в рантайме. Поскольку JavaScript сам
по себе не хранит типы и аннотации, библиотека использует механизм
reflect-metadata, который позволяет сохранять
дополнительную информацию о классах и их свойствах.
Каждое правило валидации реализуется как декоратор. При вызове функции проверки библиотека:
Таким образом, валидация становится частью модели данных.
Библиотека устанавливается через npm:
npm install class-validator reflect-metadata
Для корректной работы декораторов необходимо включить поддержку в TypeScript:
{
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
Также важно импортировать reflect-metadata один раз в
точке входа приложения:
import "reflect-metadata";
Основной способ использования — создание классов DTO (Data Transfer Object), где каждое поле описывается вместе с набором ограничений.
import { IsString, IsInt, MinLength, MaxLength } from "class-validator";
class User {
@IsString()
name;
@IsInt()
age;
@IsString()
@MinLength(5)
@MaxLength(20)
password;
}
В данном примере каждое свойство получает набор декораторов, описывающих правила проверки.
Для проверки объекта используется функция validate:
import { validate } from "class-validator";
const user = new User();
user.name = 123;
user.age = "old";
user.password = "123";
validate(user).then(errors => {
console.log(errors);
});
Результатом является массив ошибок. Если массив пустой, объект считается валидным.
Каждая ошибка содержит:
Библиотека предоставляет широкий набор встроенных декораторов, которые можно разделить на несколько групп.
Используются для проверки базовых типов данных:
@IsString()@IsNumber()@IsBoolean()@IsDate()Эти декораторы обеспечивают базовую типизацию входящих данных.
Специализированные проверки строковых значений:
@MinLength(length)@MaxLength(length)@Matches(pattern)@Contains(value)@IsEmail()Пример:
class Profile {
@IsEmail()
email;
@Matches(/^[a-zA-Z]+$/)
username;
}
Для числовых значений доступны ограничения диапазонов:
@Min(value)@Max(value)@IsPositive()@IsNegative()Эти правила позволяют ограничивать допустимые диапазоны значений.
Работа с массивами включает проверку структуры и содержимого:
@IsArray()@ArrayMinSize(n)@ArrayMaxSize(n)@ArrayNotEmpty()@ArrayUnique()Дополнительно можно проверять тип элементов внутри массива:
class Group {
@IsArray()
@IsString({ each: true })
tags;
}
Одной из ключевых возможностей class-validator является поддержка вложенных структур.
import { ValidateNested } from "class-validator";
import { Type } from "class-transformer";
class Address {
@IsString()
city;
@IsString()
street;
}
class User {
@ValidateNested()
@Type(() => Address)
address;
}
Здесь важно использование class-transformer, который
помогает корректно преобразовывать вложенные объекты в экземпляры
классов.
Когда встроенных правил недостаточно, можно создавать собственные валидаторы.
import { ValidatorConstraint, ValidatorConstraintInterface } from "class-validator";
@ValidatorConstraint({ name: "isEven", async: false })
class IsEvenConstraint {
validate(value) {
return typeof value === "number" && value % 2 === 0;
}
defaultMessage() {
return "Значение должно быть чётным числом";
}
}
import { Validate } from "class-validator";
class NumberModel {
@Validate(IsEvenConstraint)
value;
}
Кастомные валидаторы позволяют расширять систему под любые бизнес-правила.
Некоторые проверки требуют обращения к базе данных или внешним сервисам. Class-validator поддерживает асинхронные валидаторы.
@ValidatorConstraint({ async: true })
class IsUserAlreadyExist {
async validate(email) {
const user = await database.findUser(email);
return !user;
}
}
Асинхронные проверки часто используются для уникальности значений, например email или username.
Библиотека поддерживает условную валидацию через группы. Это позволяет применять разные наборы правил в зависимости от контекста.
class User {
@IsString({ groups: ["create"] })
password;
@IsString({ groups: ["update"] })
id;
}
При вызове validate можно указать группу:
validate(user, { groups: ["create"] });
С помощью @ValidateIf можно задавать условия выполнения
проверок:
class User {
@ValidateIf(o => o.isActive)
@IsString()
status;
}
Это позволяет гибко управлять логикой валидации без усложнения структуры классов.
Хотя class-validator отвечает за проверку, он часто используется
вместе с class-transformer, который выполняет
преобразование «сырых» объектов в экземпляры классов.
import { plainToInstance } from "class-transformer";
const user = plainToInstance(User, requestBody);
После этого можно безопасно запускать валидацию.
Каждая ошибка представляет собой объект со следующей структурой:
property — имя поля;constraints — список нарушенных правил;value — переданное значение;children — ошибки вложенных объектов.Пример анализа ошибок позволяет строить детализированные сообщения для пользователей или логирования.
Class-validator построен на нескольких ключевых принципах:
Такой подход делает библиотеку удобной для приложений средней и высокой сложности, где важно разделение структуры данных и логики их проверки.
Несмотря на гибкость, библиотека имеет ряд особенностей:
Эти особенности важно учитывать при проектировании архитектуры приложения, чтобы избежать некорректной валидации или потери типов.