Обработка результатов валидации

YupResolver служит адаптером между схемами валидации Yup и форм-движком (чаще всего react-hook-form). Его основная задача — преобразовать результат валидации Yup в унифицированный формат, который понимает система форм.

На выходе резолвер формирует объект следующей структуры:

  • values — валидированные данные формы (или частично валидированные, в зависимости от режима)
  • errors — нормализованная структура ошибок, совместимая с системой полей формы

Ключевой момент заключается в том, что именно обработка результата определяет поведение формы после завершения валидации: будет ли отправка данных, какие поля будут помечены ошибками и как отобразятся сообщения.


Преобразование Yup.ValidationError в errors-структуру

Yup при неуспешной валидации генерирует объект ValidationError, содержащий:

  • message — текст ошибки
  • path — путь до поля (например, user.email)
  • type — тип ошибки (если задан через test)
  • inner — массив вложенных ошибок (при abortEarly: false)

Ключевая задача резолвера

YupResolver выполняет нормализацию:

  • преобразует ValidationError в плоскую или вложенную структуру
  • сопоставляет path с ключами формы
  • агрегирует ошибки по полям
  • сохраняет приоритет сообщений

Пример логики преобразования:

  • user.emailerrors.user.email
  • items[0].nameerrors.items[0].name

Поведение при abortEarly: true

При стандартной конфигурации Yup (abortEarly: true) обработка результата упрощается:

  • возвращается только первая найденная ошибка
  • inner массив либо пустой, либо не используется
  • errors содержит минимальное количество записей

Особенности результата

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

В таком режиме YupResolver получает один ValidationError, который напрямую маппится в errors.


Поведение при abortEarly: false

При отключении раннего прерывания Yup собирает все ошибки за один проход:

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

Алгоритм обработки в YupResolver

  1. проход по error.inner
  2. группировка ошибок по path
  3. выбор приоритетного сообщения
  4. построение дерева FieldErrors

При конфликте нескольких ошибок одного поля применяется правило:

  • либо первая ошибка по порядку
  • либо ошибка с более высоким приоритетом (если настроено кастомно)

Формирование values при частичной валидации

values в результате работы YupResolver зависят от успешности проверки:

Полностью валидные данные

Если ошибок нет:

  • возвращается исходный объект, приведённый к схеме Yup
  • применяются трансформации (transform, cast)

Частично валидные данные

Если есть ошибки:

  • поведение зависит от стратегии формы

  • возможны варианты:

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

Важно, что YupResolver сам по себе не изменяет бизнес-логику значений — он лишь передаёт результат Yup.


Нормализация путей (path resolution)

Одной из сложных частей обработки результата является интерпретация путей:

  • user.email
  • user[0].email
  • items.0.name

YupResolver приводит их к формату, совместимому с системой полей:

  • dot-notation сохраняется или преобразуется
  • индексированные массивы приводятся к стабильному виду
  • обеспечивается соответствие внутреннему state формы

Проблемные случаи

  • динамические массивы (FieldArray)
  • отсутствующие промежуточные узлы
  • условные поля (presence/absence based on schema)

Обработка вложенных объектов

При работе с глубоко вложенными схемами YupResolver формирует рекурсивную структуру ошибок:

Пример:

errors: {
  user: {
    profile: {
      email: {
        type: "required",
        message: "Email обязателен"
      }
    }
  }
}

Особенности

  • каждый уровень соответствует структуре Yup schema
  • отсутствующие узлы не создаются заранее
  • ошибки создаются только при наличии нарушений

Обработка массивов и FieldArray

Массивы являются отдельным случаем трансформации результата.

Пример структуры ошибок:

items: [
  { name: { message: "Обязательное поле" } },
  null,
  { price: { message: "Некорректное значение" } }
]

Логика YupResolver:

  • индекс массива становится ключом
  • ошибки привязываются к конкретному элементу
  • пропущенные индексы заполняются undefined или null

Приоритет и конфликт ошибок

В случаях, когда одно поле генерирует несколько ошибок, применяется стратегия разрешения конфликтов:

  • первая ошибка в списке inner
  • либо последняя (в зависимости от конфигурации обработки)
  • либо кастомный редьюсер ошибок

Типичные конфликты:

  • required + min length
  • type mismatch + custom test
  • conditional schema branching

Асинхронная валидация и промисы

YupResolver поддерживает асинхронный режим:

  • validate() возвращает Promise
  • ошибки обрабатываются после завершения всех асинхронных проверок
  • результат унифицируется до одной структуры

Особенности обработки:

  • ожидание завершения всех async test
  • объединение sync и async ошибок
  • гарантированная консистентность результата

Интеграция с трансформациями Yup

Yup позволяет модифицировать данные через:

  • transform
  • cast
  • default

Влияние на result.values:

  • transform применяется до финальной валидации
  • cast влияет на итоговый тип данных
  • default заполняет отсутствующие значения

Результат в values уже содержит преобразованные данные, что снижает необходимость постобработки на уровне формы.


Поведение при кастомных тестах

Кастомные проверки (test) формируют ошибки с нестандартными type.

Особенности обработки:

  • type может быть строкой произвольного формата
  • message может зависеть от контекста
  • multiple test results могут агрегироваться в одно поле

YupResolver не интерпретирует логику теста — он лишь переносит результат.


Обработка неконсистентных структур ошибок

В некоторых случаях Yup возвращает некорректные или неполные пути:

  • отсутствующий path
  • пустой inner
  • дублирующиеся ошибки

Стратегия YupResolver:

  • игнорирование ошибок без path
  • дедупликация по path + message
  • безопасное построение дерева errors без падения выполнения

Итоговая структура результата

Обобщённый формат результата:

{
  values: {
    /* валидированные и трансформированные данные */
  },
  errors: {
    /* нормализованные ошибки по путям формы */
  }
}

Именно эта структура используется системой формы для:

  • блокировки submit
  • отображения сообщений
  • управления состоянием полей
  • синхронизации UI с результатами валидации