Библиотека class-validator строится вокруг идеи декларативной валидации через классы и декораторы. Основной подход заключается в том, что правила описываются прямо в модели данных, после чего экземпляр класса проверяется на соответствие этим правилам.
Ключевые элементы первого примера:
validate для запуска проверки.Перед использованием необходимо установить библиотеку и включить поддержку декораторов.
npm install class-validator class-transformer
Также требуется включить поддержку декораторов в TypeScript:
{
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
Если используется чистый JavaScript с Babel, необходимо подключить соответствующий плагин:
npm install --save-dev @babel/plugin-proposal-decorators
Валидация начинается с описания класса, который представляет структуру входных данных.
import { validate } from "class-validator";
import { IsString, Length, IsInt, Min, Max } from "class-validator";
class User {
@IsString()
name: string;
@IsInt()
@Min(18)
@Max(60)
age: number;
}
В данном случае задаются два поля:
name должен быть строкой;age должен быть целым числом в диапазоне от 18 до
60.После описания модели создаётся экземпляр класса и выполняется валидация.
const user = new User();
user.name = "Иван";
user.age = 17;
validate(user).then(errors => {
console.log(errors);
});
Если данные не соответствуют правилам, возвращается массив ошибок.
Результат validate представляет собой массив объектов
ValidationError. Каждый объект содержит информацию о
конкретном нарушении.
Пример упрощённой структуры:
[
{
property: "age",
constraints: {
min: "age must not be less than 18"
}
}
]
Основные поля:
property — имя поля, где обнаружена ошибка;constraints — набор нарушенных правил;children — вложенные ошибки (для вложенных
объектов).const user = new User();
user.name = "Иван";
user.age = 25;
validate(user).then(errors => {
console.log(errors); // []
});
Пустой массив означает успешное прохождение всех проверок.
Одно поле может содержать несколько ограничений одновременно.
class Product {
@IsString()
@Length(3, 20)
title: string;
@IsInt()
@Min(1)
price: number;
}
Здесь:
title должен быть строкой длиной от 3 до 20
символов;price должен быть целым числом не меньше 1.Хотя validate возвращает Promise, результат удобно
обрабатывать через async/await.
async function run() {
const product = new Product();
product.title = "TV";
product.price = 0;
const errors = await validate(product);
if (errors.length > 0) {
console.log("Ошибки валидации:", errors);
}
}
По умолчанию многие декораторы не пропускают undefined и
null, если не указано обратное.
Пример:
class Profile {
@IsString()
nickname: string;
}
Если nickname не задан, будет ошибка валидации.
Для разрешения пустых значений используется:
import { IsOptional, IsString } from "class-validator";
class Profile {
@IsOptional()
@IsString()
nickname?: string;
}
В реальных приложениях данные часто приходят в виде обычных объектов JSON. Для корректной работы class-validator требуется преобразование в экземпляр класса.
import { plainToInstance } from "class-transformer";
const raw = {
name: "Иван",
age: "20"
};
const user = plainToInstance(User, raw);
После этого объект можно безопасно валидировать:
validate(user).then(errors => {
console.log(errors);
});
Распространённая проблема заключается в попытке валидировать обычный объект без преобразования в класс:
const user = {
name: "Иван",
age: 20
};
validate(user); // некорректное использование
Декораторы работают только с экземплярами классов, поэтому требуется
создание объекта через new или
plainToInstance.
import "reflect-metadata";
import { validate, IsString, IsInt } from "class-validator";
class User {
@IsString()
name: string;
@IsInt()
age: number;
}
async function bootstrap() {
const user = new User();
user.name = "Иван";
user.age = 30;
const errors = await validate(user);
console.log(errors);
}
bootstrap();