Библиотека class-validator формирует сообщения об ошибках в строго определённой структуре, которая отражает как сам процесс валидации, так и результаты проверки каждого правила. Основной принцип заключается в том, что каждая ошибка представляет собой объект, содержащий информацию о проверяемом свойстве, значении и наборе нарушенных ограничений.
При провале валидации возвращается массив объектов
ValidationError. Каждый объект описывает одно поле или
вложенную сущность:
Пример типичного объекта:
{
property: "email",
value: "invalid-email",
target: User {
email: "invalid-email"
},
constraints: {
isEmail: "email must be an email"
},
children: []
}
Ключевым элементом структуры является поле constraints.
Оно представляет собой объект, где:
Пример:
constraints: {
isNotEmpty: "username should not be empty",
length: "username must be longer than or equal to 3 characters"
}
Если на одно поле накладывается несколько ограничений, каждое из них
добавляется отдельной записью в constraints. Это позволяет
точно определить, какие именно правила были нарушены.
Если разработчик не задаёт собственные сообщения, class-validator использует встроенные шаблоны. Они формируются на основе имени валидатора и параметров декоратора.
Примеры стандартных сообщений:
@IsEmail() → email must be an email@IsNotEmpty() →
field should not be empty@Length(3, 10) →
field must be longer than or equal to 3 and shorter than or equal to 10 characters@IsInt() →
field must be an integer numberСообщения формируются динамически, подставляя имя свойства объекта
вместо field, если не задано пользовательское имя.
Поле children используется при работе с вложенными
объектами и массивами классов. Оно повторяет структуру
ValidationError, но относится к вложенному уровню.
Пример вложенной ошибки:
{
property: "profile",
children: [
{
property: "age",
value: -1,
constraints: {
min: "age must not be less than 0"
},
children: []
}
]
}
Такая структура позволяет рекурсивно обходить дерево ошибок и точно определять источник проблемы даже в сложных DTO.
Если одно свойство нарушает несколько правил, все ошибки фиксируются одновременно:
constraints: {
isNotEmpty: "name should not be empty",
minLength: "name must be longer than or equal to 2 characters"
}
Порядок ключей в объекте constraints не гарантируется,
поскольку он зависит от внутренней реализации JavaScript-объектов и
порядка регистрации декораторов.
Поле contexts используется для передачи дополнительной
информации о конкретном ограничении. Оно появляется не всегда и обычно
заполняется при использовании кастомных валидаторов.
Пример:
contexts: {
minLength: {
constraint: 3,
value: 1
}
}
Контекст позволяет не только вывести сообщение, но и использовать дополнительные данные при построении собственных обработчиков ошибок.
Хотя сообщения по умолчанию формируются библиотекой, каждое правило может быть переопределено:
@IsEmail({}, { message: "Некорректный формат email" })
email: string;
В этом случае структура constraints сохраняется, но
значение сообщения заменяется пользовательским текстом:
constraints: {
isEmail: "Некорректный формат email"
}
При использовании ValidatorConstraint структура остаётся
той же, однако ключ в constraints соответствует имени
метода validate или имени класса валидатора.
constraints: {
isEven: "number must be even"
}
Если валидатор возвращает сложную логику проверки, в
constraints всё равно фиксируется только итоговое
сообщение, без промежуточных состояний.
При преобразовании ошибок в JSON (например, для API-ответов)
структура сохраняется полностью. Однако поля target часто
исключаются, чтобы не утяжелять ответ и не раскрывать внутренние данные
объекта.
Типичный API-ответ:
[
{
"property": "email",
"value": "invalid",
"constraints": {
"isEmail": "email must be an email"
}
}
]
Структура сообщений не является плоской. Она построена как дерево, где каждый узел может содержать:
constraints)children)Это позволяет корректно обрабатывать сложные DTO, включающие вложенные классы и массивы объектов, сохраняя точную привязку ошибки к исходной структуре данных.