Валидация числовых значений в схемах Joi строится вокруг строгого контроля диапазонов, формата и семантики числа. Особое место занимают два связанных аспекта: работа с сетевыми портами и ограничение значений безопасным диапазоном целых чисел JavaScript.
Числа в JavaScript представлены форматом IEEE-754, что накладывает ограничения на точность. Для исключения ошибок округления и некорректных значений Joi предоставляет базовые методы:
const schema = Joi.number().integer();
Данная схема гарантирует, что значение является целым числом. Любые дробные значения будут отклонены.
Дополнительно применяются ограничения диапазона:
const schema = Joi.number().integer().min(0).max(100);
Такой подход используется для ограниченных доменов значений, включая индексы, статусы и параметры конфигурации.
JavaScript способен корректно представлять целые числа только в пределах:
-(2^53 - 1) ... (2^53 - 1)
Эти значения определяются как безопасные целые числа
(Number.isSafeInteger).
В Joi используется проверка безопасного диапазона:
const schema = Joi.number().integer().safe();
Метод .safe() гарантирует:
Number.MIN_SAFE_INTEGER
и Number.MAX_SAFE_INTEGERПрименение важно в следующих сценариях:
Сетевые порты представляют собой ограниченный диапазон целых чисел от 0 до 65535. Joi предоставляет специализированную валидацию для этого случая:
const schema = Joi.number().port();
.port()Метод .port() эквивалентен проверке:
Порты часто используются вместе с конфигурационными объектами:
const configSchema = Joi.object({
host: Joi.string().hostname().required(),
port: Joi.number().port().required()
});
Такой подход позволяет строго отделить логическую структуру конфигурации от некорректных пользовательских значений.
При нарушении правил валидации Joi возвращает детализированное описание ошибки:
port вне диапазона → ошибка типа validationПример результата:
{
message: '"port" must be a valid port',
path: ['port'],
type: 'number.port'
}
Несмотря на наличие .safe(), часто требуется
дополнительная бизнес-логика:
const schema = Joi.number()
.integer()
.safe()
.min(1)
.max(9007199254740991);
Такой подход используется, когда безопасный диапазон необходимо сузить под конкретную предметную область.
Joi работает поверх особенностей языка, поэтому важно учитывать:
Number.MAX_VALUE не равен максимальному безопасному
целомуconst schema = Joi.number().integer().safe().strict();
Флаг strict() отключает автоматическое приведение типов,
что критично при работе с внешними источниками данных.
В серверных приложениях порты являются одним из наиболее частых источников ошибок конфигурации. Joi позволяет централизовать контроль:
const serverSchema = Joi.object({
port: Joi.number().port().default(3000)
});
Здесь дополнительно используется значение по умолчанию, что снижает вероятность некорректного запуска сервиса.
Несмотря на схожесть (оба работают с целыми числами), их смысл различается:
Их пересечение возможно, но не обязательно:
На практике часто встречаются следующие проблемы:
"3000" без преобразования.integer() при использовании
.port() в сложных схемахJoi позволяет строить сложные числовые ограничения через цепочку методов:
const schema = Joi.number()
.integer()
.safe()
.port()
.required();
В реальных сценариях .port() уже включает проверку
целочисленности и диапазона, поэтому дополнительные методы используются
только при нестандартных расширениях схем.
В распределённых системах числовая валидация играет роль первого уровня защиты:
Использование .safe() снижает риск некорректной
интерпретации чисел при сериализации между сервисами.
При получении данных из JSON:
{
"port": "8080"
}
валидация без strict() может привести к автоматическому
преобразованию строки в число. Это удобно, но может скрывать ошибки
входных данных.
Joi.number().port().strict();
В строгом режиме любое несоответствие типу приводит к ошибке валидации.
Комбинация механизмов Joi формирует многоуровневую защиту:
number)integer)port)safe)Эта модель позволяет строить устойчивые схемы валидации для системного и прикладного программирования без необходимости ручной обработки числовых аномалий.