Валидация на соответствие значению в Yup строится вокруг идеи строгого или наборного сравнения входных данных с заранее заданными допустимыми значениями или значениями других полей схемы. Этот механизм используется при работе с перечислениями, подтверждением полей, проверкой статусов и ограничением допустимых значений в формах и API-слоях.
Базовый механизм проверки на соответствие значению реализуется через методы, работающие с множеством допустимых значений.
Метод oneOf задаёт список допустимых значений, которым
должно соответствовать поле.
import * as Yup fr om "yup";
const schema = Yup.object({
role: Yup.string().oneOf(["admin", "editor", "viewer"])
});
В этом случае значение role должно строго совпадать с
одним из элементов массива. Любое отклонение приводит к ошибке
валидации.
Особенности поведения:
Обратный механизм позволяет запретить определённые значения:
const schema = Yup.object({
username: Yup.string().notOneOf(["admin", "root", "system"])
});
Такая проверка применяется для исключения зарезервированных слов, запрещённых статусов или конфликтующих идентификаторов.
Часто требуется сравнение не с фиксированным значением, а с другим
полем схемы. В Yup для этого используется ref.
const schema = Yup.object({
password: Yup.string().required(),
confirmPassword: Yup.string()
.oneOf([Yup.ref("password")], "Пароли должны совпадать")
});
Здесь значение confirmPassword динамически сравнивается
с password.
Ключевые особенности:
Yup.ref создаёт ссылку на другое полеconst schema = Yup.object({
min: Yup.number(),
max: Yup.number()
.min(Yup.ref("min"), "max должен быть больше или равен min")
});
Такой подход часто применяется в диапазонах значений: цены, даты, лимиты.
Стандартные методы oneOf и notOneOf
используют сравнение по ссылке или примитивное равенство. Это создаёт
важные ограничения при работе с объектами.
const schema = Yup.object({
config: Yup.object().oneOf([{ theme: "dark" }])
});
Даже если структура совпадает, объекты могут не считаться равными из-за различий в ссылках.
В таких случаях требуется использовать пользовательскую проверку.
Метод test предоставляет полный контроль над сравнением
значений.
const schema = Yup.object({
status: Yup.string().test(
"is-valid-status",
"Недопустимый статус",
value => value === "active" || value === "pending"
)
});
Сравнение может быть расширено до любой логики:
const schema = Yup.object({
price: Yup.number().test(
"compare-to-lim it",
"Цена превышает лимит",
function (value) {
const limit = this.parent.limit;
return value <= limit;
}
)
});
Здесь используется контекст this.parent для доступа к
другим полям объекта.
Механизм when позволяет изменять правила проверки в
зависимости от значения другого поля.
const schema = Yup.object({
type: Yup.string(),
value: Yup.string().when("type", {
is: "email",
then: schema => schema.email(),
otherwise: schema => schema.min(3)
})
});
Сравнение значения используется как триггер для выбора логики валидации.
Расширенный вариант:
const schema = Yup.object({
role: Yup.string().when("department", (department, schema) => {
if (department === "security") {
return schema.oneOf(["admin"]);
}
return schema.oneOf(["user", "viewer"]);
})
});
Наиболее частый кейс использования равенства полей.
const schema = Yup.object({
password: Yup.string().required(),
confirmPassword: Yup.string()
.oneOf([Yup.ref("password")], "Пароли не совпадают")
.required()
});
const schema = Yup.object({
status: Yup.string().oneOf(["draft", "published", "archived"])
});
Такая схема фиксирует допустимые состояния сущности.
const schema = Yup.object({
action: Yup.string().test(
"valid-transition",
"Недопустимый переход статуса",
function (value) {
const current = this.parent.currentStatus;
const transitions = {
draft: ["published"],
published: ["archived"],
archived: []
};
return transitions[current]?.includes(value);
}
)
});
Внутренние проверки могут давать неожиданные результаты при работе с
NaN. Валидация чисел требует дополнительной
осторожности:
Yup.number().test(
"is-not-nan",
"Некорректное число",
value => typeof value === "number" && !Number.isNaN(value)
);
undefined обычно трактуется как отсутствие
значенияnull может считаться валидным значением при явном
разрешенииYup.string().nullable().oneOf([null, "active"]);
Yup может выполнять преобразование типов перед сравнением, особенно
при использовании .transform():
Yup.number()
.transform(value => Number(value))
.oneOf([10, 20, 30]);
При работе с массивами сравнение применяется к каждому элементу:
const schema = Yup.array().of(
Yup.string().oneOf(["red", "green", "blue"])
);
Дополнительно можно проверять совпадение массива целиком через кастомные тесты:
Yup.array().test(
"match-exact",
"Массив не совпадает",
value => JSON.stringify(value) === JSON.stringify(["a", "b"])
);
Такой подход используется осторожно из-за чувствительности к порядку элементов.
Валидация может зависеть от нескольких уровней данных:
const schema = Yup.object({
minAge: Yup.number(),
age: Yup.number().test(
"greater-than-min",
"Возраст меньше допустимого",
function (value) {
return value >= this.parent.minAge;
}
)
});
Контекст позволяет строить сложные зависимости между значениями без необходимости дублирования логики вне схемы.