Валидационные схемы, построенные на основе Yup и используемые через
YupResolver, позволяют задавать строгие правила допустимых значений для
полей данных. Среди таких правил особое место занимают методы
oneOf и
notOneOf, которые обеспечивают контроль
принадлежности значения к заранее определённому набору или его
исключение из набора.
Эти методы применяются в ситуациях, когда требуется не просто проверить тип данных, а ограничить пространство допустимых значений на уровне бизнес-логики формы.
oneOfМетод oneOf задаёт перечень допустимых значений, и поле
считается валидным только в том случае, если его значение строго
совпадает с одним из элементов списка.
yup.string().oneOf(arrayOfValues, message?)
===)requiredoneOfimport * as yup from "yup";
const schema = yup.object({
role: yup.string().oneOf(["admin", "user", "moderator"])
});
В данном случае любое значение, отличное от трёх перечисленных, приведёт к ошибке валидации.
const schema = yup.object({
statusCode: yup.number().oneOf([200, 201, 204])
});
Используется для контроля допустимых кодов ответа или фиксированных числовых идентификаторов.
const schema = yup.object({
isActive: yup.boolean().oneOf([true])
});
Такой вариант фактически делает поле обязательным к установке в
true.
oneOf с
YupResolverВ связке с YupResolver схема передаётся в форму, где отклонение от допустимых значений приводит к формированию ошибки валидации.
import { useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
const schema = yup.object({
plan: yup.string().oneOf(["free", "pro", "enterprise"])
});
const form = useForm({
resolver: yupResolver(schema)
});
При вводе значения вне списка
["free", "pro", "enterprise"] поле plan
становится невалидным, а YupResolver возвращает структурированную
ошибку.
oneOfconst schema = yup.object({
role: yup.string().oneOf(
["admin", "user"],
"Недопустимая роль пользователя"
)
});
Сообщение может быть как общим, так и специфичным для поля.
notOneOfМетод notOneOf реализует противоположную логику:
значение считается допустимым, если оно не входит в указанный
список запрещённых значений.
yup.string().notOneOf(arrayOfValues, message?)
notOneOfconst schema = yup.object({
username: yup.string().notOneOf(["admin", "root", "system"])
});
Такой подход часто применяется для защиты системных или зарезервированных имён.
const schema = yup.object({
retryCount: yup.number().notOneOf([0])
});
Используется, когда определённые числовые значения считаются недопустимыми в бизнес-логике.
oneOf и notOneOf не заменяют базовую
проверку наличия значения. Валидация null,
undefined или пустой строки контролируется отдельно через
required, nullable и default.
const schema = yup.object({
role: yup.string().required().oneOf(["user", "admin"])
});
Без required поле может пройти валидацию как пустое
значение, если оно не нарушает другие ограничения.
oneOf и
notOneOf| Характеристика | oneOf |
notOneOf |
|---|---|---|
| Логика | включение | исключение |
| Поведение | допускает только перечисленные значения | запрещает перечисленные значения |
| Типичный сценарий | enum-поля | фильтрация запрещённых значений |
const schema = yup.object({
tags: yup.array().of(
yup.string().oneOf(["news", "sports", "tech"])
)
});
Каждый элемент массива проходит индивидуальную проверку.
const schema = yup.object({
settings: yup.object({
theme: yup.string().oneOf(["dark", "light"]),
language: yup.string().notOneOf(["klingon"])
})
});
oneOf и notOneOf поддерживают передачу
значений, вычисляемых на этапе выполнения.
const allowedRoles = getRolesFromServer();
const schema = yup.object({
role: yup.string().oneOf(allowedRoles)
});
Такая схема позволяет синхронизировать валидацию с серверной логикой без изменения кода формы.
Сравнение значений в oneOf и notOneOf
выполняется без приведения типов. Это означает, что:
yup.string().oneOf([1, 2, 3])
строка "1" не будет считаться равной числу
1.
При необходимости нормализации данных используется
transform:
yup.string()
.transform((value) => Number(value))
.oneOf([1, 2, 3]);
mixed
типомconst schema = yup.object({
value: yup.mixed().oneOf([true, "enabled", 1])
});
mixed позволяет задавать набор допустимых значений
разнородного типа, что полезно при интеграции с внешними API.
oneOf и notOneOf в одной схемеconst schema = yup.object({
code: yup
.string()
.oneOf(["A", "B", "C"])
.notOneOf(["C"])
});
В этом случае итоговый допустимый набор будет пересечением условий:
"A" и "B".
При конфликтующих условиях порядок применения правил влияет на
итоговое сообщение об ошибке. Обычно oneOf и
notOneOf проверяются после базовых ограничений типа
(string, number), но до кастомных
трансформаций.
При большом количестве значений (сотни и тысячи элементов)
oneOf и notOneOf могут использовать структуру
внутреннего поиска, эквивалентную проверке наличия в массиве. Для
оптимизации часто используют предварительное преобразование в
Set:
const allowed = new Set(fetchValues());
yup.string().test("oneOfSet", "", (value) => allowed.has(value));