Диапазоны значений: min, max, greater, less

Валидация числовых диапазонов в Joi строится вокруг набора ограничений, позволяющих описывать допустимые границы значений с высокой точностью. Основные механизмы включают проверки минимального и максимального порога, а также строгие сравнительные условия, определяющие относительное положение числа.

Ограничения min и max задают включительные границы диапазона. Значение считается допустимым, если оно попадает внутрь указанного интервала, включая сами границы.

const schema = Joi.number()
  .min(10)
  .max(100);

В данном случае допустимыми считаются числа от 10 до 100 включительно.

Поведение:

  • значение меньше 10 приводит к ошибке валидации;
  • значение больше 100 также считается недопустимым;
  • значения 10 и 100 проходят проверку.

Особенность этих методов заключается в том, что они работают симметрично и задают замкнутый интервал [min, max].

При работе с целыми числами и дробными значениями логика не изменяется, однако важно учитывать тип входных данных, поскольку строковые представления чисел могут приводить к предварительным преобразованиям.

Joi.number().min(0).max(1)

Такое ограничение часто используется для вероятностных значений, коэффициентов и нормализованных показателей.


greater и less

Методы greater и less задают строгие неравенства, исключающие граничные значения. Они формируют открытые интервалы.

const schema = Joi.number()
  .greater(10)
  .less(100);

Здесь допустимыми являются числа строго больше 10 и строго меньше 100.

Поведение:

  • значение 10 считается недопустимым;
  • значение 100 также отклоняется;
  • допустимыми являются все числа в диапазоне (10, 100).

Эти методы применяются в случаях, когда границы не должны включаться в область допустимых значений, например при расчётах, где крайние значения имеют отдельную семантику.


Комбинация min/max и greater/less

Обе пары методов могут использоваться совместно, однако их логика должна оставаться непротиворечивой. Внутри Joi при конфликтующих ограничениях применяется приоритет более строгих условий.

Joi.number()
  .min(0)
  .greater(-10)
  .max(100)
  .less(200);

Фактически итоговый диапазон определяется как пересечение условий:

  • greater(-10) и min(0) дают нижнюю границу 0;
  • max(100) и less(200) дают верхнюю границу 100.

Таким образом, конечный диапазон становится [0, 100].


Поведение с бесконечными границами

Если указана только одна сторона диапазона, вторая считается неограниченной.

Joi.number().min(5)

Такое правило допускает все значения от 5 и выше без верхнего ограничения.

Joi.number().less(10)

Здесь допустимы все значения меньше 10 без нижней границы.


Работа с NaN и null

При применении диапазонов важно учитывать особенности типов:

  • NaN всегда отклоняется независимо от условий;
  • null не проходит числовую валидацию без явного разрешения;
  • строковые значения преобразуются только при включённой опции преобразования.

Особенности внутренней логики

В Joi ограничения диапазона реализуются как цепочка проверок, каждая из которых добавляет условие в схему. При выполнении валидации происходит последовательная проверка:

  1. приведение типа (если включено преобразование);
  2. проверка минимальных ограничений;
  3. проверка максимальных ограничений;
  4. проверка строгих сравнений (greater, less);
  5. агрегация ошибок при нарушении условий.

При наличии нескольких конфликтующих ограничений итоговое поведение определяется пересечением допустимых множеств.


Примеры типичных сценариев

Диапазон процентных значений:

Joi.number().min(0).max(100)

Диапазон исключая границы:

Joi.number().greater(0).less(1)

Ограничение возраста:

Joi.number().min(18).max(65)

Сильное ограничение для коэффициентов:

Joi.number().greater(-1).less(1)

Приоритет строгих и включительных границ

При одновременном использовании методов, задающих включительные и исключительные границы, более строгие условия фактически сужают диапазон. Это позволяет гибко комбинировать правила без необходимости вручную пересчитывать границы.

Joi.number()
  .min(10)
  .greater(20)

Результат эквивалентен условию > 20, поскольку greater(20) сильнее min(10).

Аналогично:

Joi.number()
  .max(100)
  .less(80)

Итоговое ограничение становится < 80.


Использование в составных схемах

Диапазоны могут применяться внутри объектов и массивов, где числовые поля подчиняются локальным правилам валидации.

Joi.object({
  score: Joi.number().min(0).max(10),
  threshold: Joi.number().greater(0).less(1)
});

Такая структура позволяет задавать независимые диапазоны для различных параметров одной сущности, сохраняя строгую типизацию и предсказуемое поведение проверки.