Валидация диапазонов значений является одной из базовых задач при
работе с формами. В контексте YupResolver, который выступает адаптером
между схемами валидации Yup и библиотеками управления формами (например,
React Hook Form), механизмы min и max
используются для строгого контроля допустимых значений как для строк,
так и для числовых данных.
В Yup ограничения min и max применяются к
разным типам данных по-разному:
YupResolver не изменяет логику Yup, а лишь передаёт схему валидации, поэтому поведение строго соответствует Yup API.
При работе со строками min и max определяют
количество символов в значении.
import * as Yup from "yup";
import { yupResolver } from "@hookform/resolvers/yup";
const schema = Yup.object({
username: Yup.string()
.min(3, "Минимальная длина — 3 символа")
.max(20, "Максимальная длина — 20 символов")
.required("Поле обязательно для заполнения"),
});
В данном случае:
required.При использовании строк важно учитывать следующие особенности:
Yup работает с количеством символов, а не с байтовым представлением строки. Это особенно важно при использовании Unicode-символов, включая кириллицу и эмодзи.
Пробелы внутри строки считаются частью длины:
Yup.string().min(5);
Строка "a b c" считается длиной 5 символов.
Пустая строка "" не проходит проверку min,
если не указано nullable или не изменена логика обработки
значения.
Часто требуется предварительно обрезать пробелы:
const schema = Yup.object({
email: Yup.string()
.transform(value => value?.trim())
.min(5)
.max(50)
.required(),
});
В этом случае длина считается после удаления пробелов по краям, что уменьшает количество ложных ошибок валидации.
Для чисел min и max задают допустимый
диапазон значений.
const schema = Yup.object({
age: Yup.number()
.min(18, "Минимальный возраст — 18 лет")
.max(65, "Максимальный возраст — 65 лет")
.required("Возраст обязателен"),
});
Здесь значение должно находиться в диапазоне от 18 до 65 включительно.
Yup строго различает строки и числа. Значение "25"
(строка) не будет автоматически считаться числом без преобразования.
Для корректной работы часто используется transform или
typeError:
Yup.number()
.typeError("Введите число")
.min(10)
.max(100);
Если значение не может быть преобразовано в число, Yup возвращает
NaN, что приводит к ошибке валидации.
min и max являются включительными:
min(10) допускает значение 10;max(20) допускает значение 20.На практике ограничения часто комбинируются с другими методами Yup.
const schema = Yup.object({
password: Yup.string()
.min(8)
.max(32)
.matches(/[A-Z]/, "Должна быть хотя бы одна заглавная буква")
.matches(/[0-9]/, "Должна быть хотя бы одна цифра")
.required(),
});
Здесь min и max задают базовый диапазон
длины, а matches добавляет структурные ограничения.
При использовании nullable и notRequired
поведение меняется:
Yup.string()
.min(3)
.max(10)
.nullable()
.notRequired();
null не проходит проверку длины, если не настроено
иначе;Yup позволяет задавать динамические значения min/max через функции:
const schema = Yup.object({
password: Yup.string().min(
8,
({ min }) => `Минимум ${min} символов`
),
});
Также можно использовать внешние переменные:
const MIN_LENGTH = 5;
const MAX_LENGTH = 15;
Yup.string()
.min(MIN_LENGTH)
.max(MAX_LENGTH);
Часто min/max зависит от другого поля формы:
const schema = Yup.object({
minValue: Yup.number().required(),
maxValue: Yup.number()
.min(Yup.ref("minValue"), "Не может быть меньше минимального значения")
});
В этом случае min использует ссылку на другое поле
формы, обеспечивая согласованность данных.
При использовании YupResolver схема передаётся в resolver без изменений:
import { useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
const {
register,
handleSubmit,
formState: { errors }
} = useForm({
resolver: yupResolver(schema),
});
Ошибки, возвращаемые min и max,
автоматически попадают в errors и могут быть отображены в
интерфейсе.
Числа приходят как строки из input:
Yup.number().min(10);
без valueAsNumber в форме приводит к некорректной
валидации.
Пустая строка может проходить как валидное значение без
required, что нарушает бизнес-логику.
Emoji и сложные Unicode-символы могут восприниматься как один символ, хотя визуально занимают больше места.
Хотя основной фокус min и max — строки и
числа, для массивов они работают как ограничение длины:
Yup.array()
.min(1, "Нужно выбрать хотя бы один элемент")
.max(5, "Максимум 5 элементов");
Это важно при работе с чекбоксами и множественным выбором.
min и max являются декларативными
ограничителями диапазона;