Валидация на основе схемы Yup формирует ошибки в стандартизированном
виде, который затем интерпретируется резолверами, включая YupResolver.
Центральной единицей является объект ValidationError,
содержащий:
message — текст ошибкиpath — путь до поля в формеtype — тип ошибки (например, required,
min, matches)inner — массив вложенных ошибок (при множественной
валидации)Ключевым свойством для маппинга является path. Именно он
определяет, в какое поле формы будет записана ошибка.
Резолвер выполняет трансформацию:
Yup ValidationError → { fieldName: { message, type } }
или для вложенных структур:
user.address.city → errors.user.address.city
Основная задача YupResolver — привести иерархию ошибок Yup к структуре, совместимой с формой, где каждое поле имеет доступ к своей ошибке.
При отключённом abortEarly: true, Yup возвращает сразу
все ошибки:
{
inner: [
{ path: "email", message: "Email некорректен" },
{ path: "password", message: "Слишком короткий пароль" }
]
}
Резолвер проходит по массиву inner и агрегирует их в
объект:
pathЕсли inner пустой, используется корневой
ValidationError.
Преобразование выполняется по шагам:
path вида:
user.nameitems[0].titleprofile.address.cityприводится к сегментированной структуре:
["user", "name"]
["items", "0", "title"]
["profile", "address", "city"]
Создаётся вложенный объект:
errors.user.name = { message, type }
errors.items[0].title = { message, type }
Индексы массивов приводятся к числовым ключам, чтобы корректно совпадать с field array структурами:
items.0.title → errors.items[0].title
Вложенные структуры требуют рекурсивного маппинга:
const schema = yup.object({
user: yup.object({
profile: yup.object({
age: yup.number().required()
})
})
});
Ошибка:
user.profile.age
Результат:
errors.user.profile.age.message
Резолвер обязан сохранять полную вложенность без потери контекста.
Массивы являются наиболее сложным случаем, так как сочетают:
Пример:
items: [
{ title: "" },
{ title: "Valid" }
]
Ошибка Yup:
items[0].title: "Обязательное поле"
Маппинг:
errors.items[0].title
При удалении элементов важно сохранять согласованность индексов, иначе ошибки будут «съезжать» на другие элементы массива.
Если одно поле возвращает несколько ошибок, применяется стратегия:
abortEarly: true)innerРезолвер может конфигурироваться:
Стандартный формат:
{
message: string,
type: string
}
Расширенный формат:
{
message: string,
type: string,
ref: any,
types: object
}
types используется для сложных схем (например, min +
required одновременно).
Yup позволяет генерировать кастомные ошибки:
yup.string().test("custom", function (value) {
return value === "admin"
? true
: this.createError({ message: "Недопустимое значение" });
});
Резолвер обязан:
messagepathtype (если задан)Некоторые случаи приводят к отсутствию path:
this)Решение:
root)formErrorUI-слой ожидает формат:
{
fieldName: {
message: string,
type: string
}
}
Резолвер выполняет:
undefinedПри больших формах (100+ полей) маппинг может быть дорогим. Используются техники:
При пересечении путей:
user.email
user.email.confirm
Возможны конфликты при агрегации. Резолвер обязан:
При условной валидации:
yup.object({
isCompany: yup.boolean(),
companyName: yup.string().when("isCompany", {
is: true,
then: yup.string().required()
})
});
Маппинг ошибок зависит от состояния схемы на момент резолва. Это означает:
Функционально процесс можно представить как:
Input: Yup ValidationError tree
↓
Flatten inner errors
↓
Normalize path strings
↓
Build nested object by segments
↓
Attach { message, type }
↓
Return form-compatible error map
Роль YupResolver заключается в обеспечении детерминированного преобразования ошибок схемы в структуру, пригодную для отображения в UI без дополнительной постобработки.