В основе диагностики поведения схем в Yup лежит объект
ValidationError. Он формируется при любом несоответствии
данных описанной схеме и содержит не только текст ошибки, но и
структурированную информацию о месте возникновения проблемы.
Ключевые поля ValidationError:
user.email, items[2].price)Именно inner становится основным инструментом анализа
сложных структур, где одна схема включает множество вложенных
проверок.
Типичная ошибка при отсутствии анализа inner —
восприятие только первой проблемы, хотя фактическая причина может
находиться глубже в структуре.
По умолчанию Yup останавливает валидацию при первой найденной ошибке
(abortEarly: true). Это значительно усложняет отладку, так
как скрывает остальные проблемы.
Изменение поведения:
schema.validate(data, { abortEarly: false })
или
Yup.object().shape({...}).validate(data, { abortEarly: false })
При отключении раннего прерывания:
innerОднако увеличивается объем информации, которую нужно структурировать вручную.
Поле path является ключевым инструментом точечного
поиска проблем.
Пример структуры:
const schema = Yup.object({
user: Yup.object({
email: Yup.string().email(),
}),
});
При ошибке email:
path: "user.email"
Для массивов:
items[3].price
Это позволяет:
Частая проблема — игнорирование path и попытка
анализировать только message, что приводит к потере
контекста.
В сложных схемах (особенно array().of(object()))
основная информация скрывается в inner.
Структура:
inner: [
{ path: "items[0].name", message: "Required" },
{ path: "items[2].price", message: "Must be positive" }
]
Методика анализа:
pathОсобенно важно при динамических массивах, где индексы элементов меняются.
Yup поддерживает два режима:
validate() — асинхронный (Promise)validateSync() — синхронныйОтладка различается:
Типичная ошибка — смешивание режимов в одном потоке обработки данных, что приводит к “потерянным” исключениям.
При сложной композиции схем полезно анализировать не только данные, но и саму структуру валидации.
Подходы:
console.log(schema.describe());
Результат содержит:
Это помогает выявить:
number vs string)shapeМетод transform() часто становится скрытым источником
ошибок.
Yup.string().transform(value => value.trim())
Проблемы:
undefinedПри дебаге важно временно отключать трансформации, чтобы определить, на каком этапе возникает искажение данных.
Метод when() создаёт динамическую схему, поведение
которой зависит от входных данных.
Пример:
Yup.string().when("isAdmin", {
is: true,
then: schema => schema.required(),
})
Проблема:
describe() не отражает
реальное состояниеПри отладке важно фиксировать входные условия, при которых формируется схема.
Метод reach() позволяет изолировать конкретную ветку
схемы:
Yup.reach(schema, "user.profile.email")
Используется для:
Это особенно эффективно при глубокой вложенности объектов.
Yup.number().required()
при передаче строки "123" может не работать без
coercion.
Решение:
transformtypeErrorYup.string().email()
Поле может проходить как undefined, если не указан
required().
Yup.string().nullable()
Без дополнительной проверки required() допускает
null, но не всегда это ожидаемое поведение.
Yup.object().stripUnknown(true)
Без этого неизвестные поля могут попадать в результат, и это создаёт ложное ощущение корректной валидации.
При сложных объектах эффективной стратегией является пошаговое упрощение:
Этот метод особенно полезен при схемах с множеством
when, array.of, lazy.
Массивы — наиболее проблемная зона в Yup.
Yup.array().of(
Yup.object({
name: Yup.string().required(),
})
)
Основные проблемы:
innerabortEarly: falseДля диагностики важно анализировать:
inner[].pathИспользование unit-тестов позволяет выявлять ошибки схем до интеграции:
Типичный паттерн:
expect(schema.isValid(data)).toBe(false)
или
await expect(schema.validate(data)).rejects.toThrow()
Стандартные сообщения Yup часто недостаточно информативны в сложных системах.
Подходы улучшения:
messagetest()Пример:
Yup.string().test("len", "INVALID_LENGTH", value => value.length > 3)
Это упрощает интеграцию с логированием и UI-валидацией.
Функция test() может быть асинхронной:
Yup.string().test("check-db", async value => {
return await check(value);
});
Проблемы:
Для отладки важно временно заменять асинхронные проверки на синхронные заглушки.
validate() — возвращает данные или ошибкуisValid() — boolean без деталейПри дебаге предпочтителен validate(), так как он
предоставляет:
isValid() используется только для быстрых проверок без
диагностики.
Эффективная диагностика строится на сочетании:
ValidationError.innerreachdescribe()abortEarlyГлавная сложность Yup-схем — их декларативность: ошибка часто не находится в месте, где она проявляется, а возникает в трансформациях, условиях или вложенных объектах.