Числовые ограничения для bigint

В библиотеке Zod тип bigint представлен отдельным примитивом схемы и поддерживает набор числовых ограничений, аналогичных числам, но реализованных с учётом особенностей произвольной точности. Использование bigint особенно важно в сценариях работы с криптографией, финансовыми вычислениями, идентификаторами и системами, где диапазон значений превышает возможности number.

Базовая схема bigint

Создание схемы начинается с базового конструктора:

import { z } from "zod";

const schema = z.bigint();

Такая схема принимает любое значение типа bigint без ограничений по диапазону.

Примеры допустимых значений:

schema.parse(10n);
schema.parse(0n);
schema.parse(-999999999999999999n);

Любое значение типа number или string будет отклонено, даже если оно выглядит числовым.


Минимальные и максимальные ограничения

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

const schema = z.bigint().min(10n).max(100n);

Поведение:

  • 10n — допустимо
  • 100n — допустимо
  • 9n — ошибка
  • 101n — ошибка

Ограничения могут применяться по отдельности:

z.bigint().min(0n);  // только неотрицательные значения
z.bigint().max(1000n); // верхняя граница без нижней

Строгие неравенства: gt, gte, lt, lte

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

Больше и больше или равно

z.bigint().gt(10n);   // строго больше 10n
z.bigint().gte(10n);  // больше или равно 10n

Разница:

  • gt(10n) исключает 10n
  • gte(10n) включает 10n

Меньше и меньше или равно

z.bigint().lt(100n);  // строго меньше 100n
z.bigint().lte(100n); // меньше или равно 100n

Комбинирование ограничений

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

const schema = z.bigint().gte(1n).lt(1000n);

Такой вариант задаёт полуоткрытый интервал:

  • минимальное значение включено
  • максимальное значение исключено

Другой пример:

const schema = z.bigint().gt(0n).lt(10n);

Допустимые значения: от 1n до 9n.


Ограничения знака числа

Для удобства предусмотрены предустановленные ограничения:

z.bigint().positive();   // > 0n
z.bigint().nonnegative(); // >= 0n
z.bigint().negative();   // < 0n
z.bigint().nonpositive(); // <= 0n

Эти методы эквивалентны комбинациям базовых сравнений:

  • positive()gt(0n)
  • nonnegative()gte(0n)
  • negative()lt(0n)
  • nonpositive()lte(0n)

Поведение при нарушении ограничений

При несоответствии значения любому из условий схема возвращает структурированную ошибку валидации. Пример:

const schema = z.bigint().min(10n);

schema.parse(5n);

Результат: ошибка, указывающая на несоответствие минимальному значению.

Внутренне Zod формирует список issues, где фиксируется:

  • ожидаемое ограничение
  • фактическое значение
  • путь в объекте (если применимо)

Совместимость ограничений

Ограничения bigint не смешиваются с number:

z.bigint().min(1); // некорректно

Даже если значение выглядит числом, оно должно быть явно bigint:

z.bigint().min(1n); // корректно

Это связано с тем, что bigint и number — разные типы в JavaScript, и их сравнение требует строгой типизации.


Использование refine для сложных условий

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

const schema = z.bigint().refine((val) => val % 2n === 0n);

Здесь проверяется чётность значения.

Можно комбинировать с диапазонами:

const schema = z
  .bigint()
  .min(10n)
  .max(1000n)
  .refine((val) => val % 5n === 0n);

В этом случае значение должно:

  • находиться в диапазоне
  • делиться на 5 без остатка

Типичные сценарии применения ограничений bigint

Идентификаторы с ограниченным диапазоном

const idSchema = z.bigint().positive().max(10_000_000n);

Финансовые значения в минимальных единицах

const moneySchema = z.bigint().nonnegative().min(100n);

Криптографические параметры

const keySchema = z.bigint().gt(2n ** 1023n);

Особенности сравнения и производительности

Операции сравнения bigint выполняются на уровне языка JavaScript и не приводят к потерям точности, в отличие от number. Ограничения Zod не преобразуют типы, а работают поверх нативных сравнений, что исключает ошибки округления.

При этом:

  • сравнение bigint и number недопустимо
  • любые неявные преобразования отсутствуют
  • все границы должны быть строго bigint

Поведение при сериализации и парсинге

При использовании JSON данные типа bigint требуют предварительного преобразования, поскольку JSON не поддерживает этот тип.

JSON.stringify(10n); // ошибка

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


Сочетание с трансформациями

Ограничения могут использоваться совместно с преобразованиями:

const schema = z
  .bigint()
  .min(0n)
  .transform((val) => val.toString());

Здесь происходит:

  • проверка диапазона
  • преобразование в строку

Такой подход часто применяется при сериализации значений для API.


Пограничные случаи

Некоторые сценарии требуют особой осторожности:

  • отрицательные значения в nonnegative()
  • равенство граничным значениям при gt/lt
  • использование refine без учёта базовых ограничений

Пример конфликтного определения:

z.bigint().gt(10n).lt(10n);

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