Числовая схема в Yup строится вокруг базового валидатора, который
обеспечивает проверку, приведение и ограничение значений типа number.
Основой служит вызов yup.number(), возвращающий схему,
предназначенную для работы с числовыми данными в формах, API-ответах и
любых структурах, где требуется строгая типизация значений.
Внутренне схема числа работает в двух режимах: приведение (casting) и валидация. Приведение отвечает за преобразование входного значения в число, если это возможно, а валидация — за проверку соответствия заданным правилам. Это разделение важно, поскольку входные данные часто приходят в виде строк, особенно в контексте HTML-форм.
import * as yup from 'yup';
const schema = yup.number();
Такой вариант допускает любые числовые значения, включая
NaN, Infinity, -Infinity, если не
заданы дополнительные ограничения. Это важно учитывать при
проектировании схем, так как Yup по умолчанию не ограничивает
математический диапазон.
Числовая схема активно использует преобразование типов. Значения типа string, содержащие числа, автоматически приводятся:
yup.number().validateSync("42"); // 42
yup.number().validateSync("3.14"); // 3.14
Пустые строки при этом преобразуются в NaN, что часто
требует дополнительной обработки:
yup.number().nullable().transform((value, originalValue) => {
return originalValue === "" ? null : value;
});
Функция transform позволяет полностью контролировать
процесс преобразования входных данных до этапа валидации. Это особенно
важно при работе с формами, где пустые значения часто представлены
строками.
Для указания обязательности используется метод
required:
yup.number().required();
Отсутствие значения или undefined приведёт к ошибке
валидации. Однако null по умолчанию не считается допустимым
значением, если не указано явно:
yup.number().nullable().required();
Комбинация nullable и required позволяет
различать отсутствие значения и его явное обнуление.
Для чисел часто применяются ограничения диапазона:
yup.number().min(0);
yup.number().max(100);
Метод min задаёт нижнюю границу включительно,
max — верхнюю. Эти ограничения работают после приведения
типов, что означает, что строковые значения сначала преобразуются в
числа.
Также существуют строгие варианты:
yup.number().moreThan(0); // строго больше
yup.number().lessThan(100); // строго меньше
Эти методы полезны при исключении граничных значений, например в процентах или коэффициентах.
Часто требуется ограничить знак числа:
yup.number().positive();
yup.number().negative();
yup.number().nonNegative();
yup.number().nonPositive();
positive исключает ноль, тогда как
nonNegative допускает его. Аналогично работает пара
negative и nonPositive.
Для проверки целочисленного значения используется метод:
yup.number().integer();
Он исключает дробные значения. При этом значения вида
"10.0" после приведения могут считаться валидными или
невалидными в зависимости от результата кастинга.
По умолчанию NaN считается невалидным значением. Это
поведение можно контролировать через трансформации:
yup.number().transform((value, originalValue) => {
return isNaN(value) ? undefined : value;
});
Infinity и -Infinity также считаются числами JavaScript, но часто исключаются бизнес-логикой через кастомные тесты:
yup.number().test(
'finite',
'Значение должно быть конечным числом',
(value) => Number.isFinite(value)
);
Механизм test позволяет добавлять произвольную
логику:
yup.number().test(
'is-even',
'Число должно быть чётным',
(value) => value % 2 === 0
);
Каждый тест получает значение после преобразования и может возвращать
true или false. Также допускается асинхронная
проверка:
yup.number().test(
'async-check',
'Недопустимое значение',
async (value) => {
const result = await someApiCheck(value);
return result.valid;
}
);
Схема может задавать значение по умолчанию:
yup.number().default(0);
Это значение применяется при отсутствии входных данных. Важно, что
default не заменяет null, если не используется
дополнительная логика трансформации.
Режим strict отключает автоматическое приведение
типов:
yup.number().strict();
В этом случае строка "42" не будет преобразована в число
и вызовет ошибку. Это используется в системах, где требуется строгий
контроль входных данных без неявных преобразований.
Числовая схема может зависеть от других полей через
when:
yup.number().when('minValue', (minValue, schema) => {
return schema.min(minValue);
});
Такой подход позволяет строить динамические ограничения, зависящие от контекста формы или состояния данных.
При кастинге строк в числа учитываются особенности JavaScript
Number(), который не поддерживает локализованные
форматы:
yup.number().validateSync("1,5"); // NaN
Для поддержки локалей требуется предварительная трансформация:
yup.number().transform((value, originalValue) => {
if (typeof originalValue === 'string') {
return parseFloat(originalValue.replace(',', '.'));
}
return value;
});
Числовая схема часто представляет цепочку ограничений:
yup.number()
.required()
.integer()
.min(1)
.max(100)
.positive();
Каждое правило применяется последовательно, и ошибка возникает на первом нарушенном условии, если не настроено накопление ошибок.
В Yup сначала выполняется трансформация, затем кастинг, после чего
идут синхронные и асинхронные тесты. Это означает, что изменение
входного значения через transform влияет на все последующие
этапы.
yup.number()
.transform((value) => value * 2)
.min(10);
В данном случае проверка min(10) применяется уже к
преобразованному значению.
Каждый метод поддерживает кастомные сообщения:
yup.number().min(10, 'Минимальное значение — 10');
Также сообщения могут формироваться через функции:
yup.number().max(100, ({ max }) => `Максимум: ${max}`);
Это позволяет адаптировать текст ошибок под контекст интерфейса.
Числовая схема интегрируется с системой типов:
const schema: yup.NumberSchema<number | undefined> = yup.number();
Это позволяет выводить тип результата в зависимости от настроек
required, nullable и default.
Особенно важно учитывать, что результат валидации может отличаться от входного типа из-за кастинга.
Разные комбинации методов дают различное поведение:
number() — допускает undefinedrequired() — исключает undefinednullable() — допускает nulldefault() — подставляет значение при отсутствииЭти параметры формируют базовую модель допустимых состояний числа и требуют согласованной настройки при проектировании схемы данных.