Параметр validationError.value

В библиотеке class-validator объект ValidationError формируется при провале проверки одного из полей класса-валидатора. Он содержит детализированную информацию о том, какое именно значение нарушило правила валидации, какие ограничения были заданы и какова структура вложенных ошибок.

Одним из ключевых элементов этой структуры является свойство value, фиксирующее исходное значение поля на момент выполнения валидации.


Структура ValidationError

Типичный объект ValidationError включает несколько взаимосвязанных полей:

  • property — имя свойства объекта, которое прошло проверку
  • value — фактическое значение, вызвавшее ошибку
  • target — исходный объект, на котором выполнялась валидация
  • constraints — набор нарушенных правил с текстами ошибок
  • children — вложенные ошибки для сложных объектов

Именно комбинация value, constraints и children позволяет реконструировать контекст возникновения ошибки без дополнительного логирования входных данных.


Свойство value как источник фактического состояния данных

value отражает текущее значение свойства, которое было проверено валидатором. Это значение фиксируется до преобразований или после частичной трансформации, в зависимости от конфигурации пайплайна.

В простейшем случае поведение выглядит следующим образом:

  • входное значение попадает в объект DTO
  • применяется набор декораторов валидации
  • при нарушении условий формируется ValidationError
  • в value сохраняется значение, которое не прошло проверку

Пример логического представления:

{
  property: "age",
  value: -5,
  constraints: {
    min: "age must not be less than 0"
  }
}

В данном случае value фиксирует число -5, так как именно оно стало причиной нарушения ограничения min.


Поведение value при преобразовании типов

В связке с class-transformer значение value может отличаться от исходного входного payload. Это особенно заметно при использовании transform: true.

При включённой трансформации:

  • строки могут быть преобразованы в числа
  • plain objects могут становиться экземплярами классов
  • массивы приводятся к типизированным структурам

В результате value отражает уже преобразованное значение, а не исходный сырой input.

Пример:

// входные данные
{ age: "18" }

После трансформации:

{
  property: "age",
  value: 18,
  constraints: {
    min: "age must not be less than 0"
  }
}

Здесь критически важно, что value уже приведено к числу.


Отличие value от target

Существенная разница между value и target заключается в уровне представления данных:

  • value — конкретное значение поля
  • target — объект DTO целиком

Пример структуры:

{
  property: "email",
  value: "invalid-email",
  target: UserDto {
    email: "invalid-email",
    age: 25
  }
}

value полезен при точечной диагностике, тогда как target используется для анализа всего контекста состояния объекта.


Поведение value при вложенных структурах

При работе с вложенными объектами и массивами value сохраняет локальный фрагмент данных, относящийся к конкретному уровню валидации.

Пример вложенной структуры:

class User {
  @ValidateNested()
  profile: Profile;
}

class Profile {
  @IsString()
  name: string;
}

При ошибке:

{
  property: "profile",
  value: {
    name: 123
  },
  children: [
    {
      property: "name",
      value: 123,
      constraints: {
        isString: "name must be a string"
      }
    }
  ]
}

Здесь верхнеуровневый value содержит весь объект profile, а вложенные ошибки уточняют проблемное поле.


Работа value в массивах

При валидации массивов value отражает:

  • либо конкретный элемент массива
  • либо весь массив на уровне родительского поля

Пример:

{
  property: "tags",
  value: ["js", 123, "node"],
  children: [
    {
      property: "1",
      value: 123,
      constraints: {
        isString: "each value in tags must be a string"
      }
    }
  ]
}

В данном случае:

  • верхний value показывает состояние массива целиком
  • вложенная ошибка указывает на конкретный индекс

Поведение value при частичной валидации

При использовании опций skipMissingProperties или whitelist, значение value может быть:

  • undefined, если поле отсутствует
  • null, если явно передано пустое значение
  • частично очищенным объектом, если применена фильтрация свойств

Пример:

{
  property: "username",
  value: undefined,
  constraints: {
    isNotEmpty: "username should not be empty"
  }
}

Такое состояние указывает на отсутствие данных до этапа проверки ограничений.


value и пользовательские валидаторы

При создании кастомных декораторов value передаётся в функцию проверки как текущий аргумент.

function customValidator(value) {
  return typeof value === "string" && value.length > 3;
}

При ошибке:

{
  property: "code",
  value: "ab",
  constraints: {
    customValidator: "code is invalid"
  }
}

Здесь value позволяет точно определить состояние данных внутри пользовательской логики.


Изменяемость value и неизменяемость контекста

Несмотря на то что value отражает текущее состояние данных, он не предназначен для модификации. Изменение этого поля не влияет на исходный объект валидации и не пересчитывает ошибки.

Фактически:

  • value — диагностическое значение
  • источник данных хранится в target

Попытки изменения value не приводят к обновлению состояния валидации и не пересоздают структуру ошибок.


Типичные случаи интерпретации value

На практике значение value используется для:

  • логирования некорректных входных данных
  • построения API-ответов с описанием ошибок
  • трассировки проблем в сложных DTO
  • анализа трансформаций данных перед валидацией

Особое значение имеет сохранение оригинального типа данных, так как именно через value определяется расхождение между ожидаемой и фактической формой данных.


Особенности сериализации ValidationError

При сериализации объектов ошибок в JSON:

  • value сохраняется в исходной форме, если сериализация не ограничена
  • вложенные структуры могут быть упрощены в зависимости от реализации API слоя
  • объекты классов часто преобразуются в plain object, но value остаётся ключевым диагностическим полем

Пример сериализованного представления:

{
  property: "price",
  value: "free",
  constraints: {
    isNumber: "price must be a number"
  }
}

Даже после сериализации значение остаётся тем же, что было на этапе проверки.


Роль value в диагностике сложных схем

В сложных схемах DTO с множественными уровнями вложенности value становится основным ориентиром для определения:

  • на каком уровне произошёл сбой
  • какой именно тип данных был передан
  • как изменилось значение после трансформации

В сочетании с children оно позволяет реконструировать полное дерево состояния данных в момент ошибки.


Поведение value при комбинированных валидаторах

При использовании нескольких декораторов на одном свойстве:

@IsString()
@Length(5, 10)
username: string;

в случае ошибки value остаётся одинаковым для всех нарушенных ограничений, так как оно фиксирует общее значение поля, а не конкретный тип ошибки.

Пример:

{
  property: "username",
  value: "ab",
  constraints: {
    length: "username must be longer than 5 characters",
    isString: "username must be a string"
  }
}

Связь value и порядка валидации

Порядок применения валидаторов не изменяет содержимое value. Однако влияет на набор constraints. Независимо от того, какое правило сработало первым, value остаётся неизменным источником входного состояния.


Использование value в сложных пайплайнах

В реальных приложениях с многоступенчатой обработкой данных value часто проходит через:

  • трансформацию DTO
  • валидацию бизнес-правил
  • фильтрацию входных данных
  • сериализацию ответа

На каждом этапе оно сохраняет своё диагностическое значение, позволяя отслеживать расхождения между слоями обработки.