Декоратор @IsDivisibleBy из библиотеки
class-validator применяется для проверки числового
значения на кратность заданному делителю. В основе лежит строгая
математическая проверка остатка от деления: значение считается валидным,
если остаток равен нулю.
Ключевая особенность — ориентация исключительно на числовую семантику. Проверка не выполняет преобразований типов и не пытается интерпретировать строковые значения как числа без дополнительной трансформации.
Декоратор применяется к свойству класса и принимает единственный обязательный аргумент — делитель.
IsDivisibleBy(value: number, validationOptions?: ValidationOptions)
value — число, на которое должно делиться проверяемое
значениеvalidationOptions — стандартные опции
class-validator (сообщения, группы, условия
применения)Простейшая форма:
import { IsDivisibleBy } fr om 'class-validator';
class ExampleDto {
@IsDivisibleBy(5)
amount: number;
}
В данном случае значение amount считается корректным
только если оно кратно 5.
Логика проверки базируется на выражении:
[ value divisor = 0]
где:
value — проверяемое числоdivisor — аргумент декоратораЭквивалентная логика на уровне реализации:
value % divisor === 0
При этом используется поведение JavaScript-оператора %,
включая особенности работы с отрицательными числами и дробными
значениями.
Декоратор не выполняет приведение типов:
class ExampleDto {
@IsDivisibleBy(3)
value: number;
}
| Входное значение | Результат |
|---|---|
| 9 | валидно |
| 10 | невалидно |
| “9” | невалидно |
| null | невалидно |
| undefined | невалидно |
Для обработки строковых чисел требуется предварительная трансформация
через class-transformer.
JavaScript допускает дробные значения в операции остатка, что приводит к нетривиальным результатам.
9.6 % 3 // 0.5999999999999996
Следовательно:
@IsDivisibleBy(3)
value: number;
значение 9.6 будет считаться невалидным.
Особенности:
% с
нулёмПоведение для отрицательных значений соответствует спецификации Jav * aScript:
-9 % 3 === 0
Следовательно:
| Значение | Делитель | Результат |
|---|---|---|
| -9 | 3 | валидно |
| -10 | 3 | невалидно |
Знак числа не влияет на кратность.
Типичный сценарий — валидация входных данных в транспортных объектах.
import { IsDivisibleBy, IsInt } from 'class-validator';
class PaginationDto {
@IsInt()
@IsDivisibleBy(10)
lim it: number;
}
Здесь комбинирование ограничений усиливает семантику:
@IsInt() исключает дробные значения@IsDivisibleBy(10) ограничивает шаг значений@IsNumberЧасто используется для предотвращения строковых значений:
import { IsNumber, IsDivisibleBy } from 'class-validator';
class ExampleDto {
@IsNumber()
@IsDivisibleBy(4)
value: number;
}
Без @IsNumber возможно прохождение некорректных данных
при неправильной трансформации входа.
@IsOptionalПри добавлении @IsOptional проверка делимости не
выполняется для null и undefined:
class ExampleDto {
@IsOptional()
@IsDivisibleBy(2)
value?: number;
}
0 и
делителеОсобое внимание требует делитель:
@IsDivisibleBy(0)
value: number;
Деление на ноль в JavaScript приводит к особенностям вычисления
%:
value % 0 → NaNNaN === 0 → falseСледовательно, при делителе 0 все значения считаются
невалидными.
NaN % 3 // NaN
Любое значение NaN автоматически проваливает
проверку.
Infinity % 3 // NaN
Значения Infinity и -Infinity также
считаются невалидными.
При работе с Number.MAX_SAFE_INTEGER возможны потери
точности, что влияет на корректность остатка от деления.
При использовании class-transformer типичная цепочка
выглядит следующим образом:
transform преобразует их в числаclass-validator выполняет проверку
@IsDivisibleByБез трансформации:
class ExampleDto {
@IsDivisibleBy(2)
value: number;
}
вход "8" будет отклонён, поскольку тип остаётся
строкой.
При включении whitelist и
forbidNonWhitelisted в NestJS-подобных системах
@IsDivisibleBy остаётся исключительно проверочным
механизмом и не влияет на структуру объекта, но участвует в общем
результате валидации:
ValidationErrorValidationOptionsВозможна настройка текстов ошибок:
@IsDivisibleBy(3, {
message: 'Значение должно быть кратно 3'
})
value: number;
Сообщение может зависеть от контекста через функции:
@IsDivisibleBy(5, {
message: ({ value }) => `${value} не делится на 5 без остатка`
})
Используется для контроля шагов в пагинации:
class QueryDto {
@IsDivisibleBy(20)
pageSize: number;
}
Ограничение кратности суммы:
class PaymentDto {
@IsDivisibleBy(100)
amount: number;
}
class ScheduleDto {
@IsDivisibleBy(15)
intervalMinutes: number;
}
%Эти особенности делают поведение предсказуемым в рамках JavaScript, но чувствительным к типу входных данных и источнику преобразования.