Type Formats

Number Formats

Integers, fixed-width ints, signs and money amounts.

Named Number Formats

Each format is a TF.Number with its params set, and has a builder named in lowercase (TF.int32(), TF.positive()). For your own bounds, see Custom Number Formats.

const isInt8 = createValidateFn<TF.Int8>();
const isUInt8 = createValidateFn<TF.UInt8>();
const isPositive = createValidateFn<TF.Positive>();

isInt8(-128); // true
isInt8(1.5); // false, not a whole number
isUInt8(256); // false, over 255
isPositive(0); // true
FormatAccepts
TF.Integera whole number
TF.Floatany number; mocks draw fractional values
TF.Positive / TF.Negative>= 0 / <= 0
TF.PositiveInt / TF.NegativeInta whole number >= 0 / <= 0
TF.Int8, TF.Int16, TF.Int32a whole number that fits the signed width
TF.UInt8, TF.UInt16, TF.UInt32a whole number that fits the unsigned width
TF.Currencyany number, marked as money
TF.Positive and TF.Negative include zero. Write TF.Number<{gt: 0}> for a strictly positive number.

Custom Number Formats

Use TF.Number with your own bounds when no named format fits.

type PackSize = TF.Number<{gt: 0; multipleOf: 6}>;
type Percent = TF.Number<{min: 0; max: 100; integer: true}>;

const isPackSize = createValidateFn<PackSize>();
const isPercent = createValidateFn<Percent>();

isPackSize(12); // true
isPackSize(0); // false, must be over 0
isPackSize(10); // false, not a multiple of 6
isPercent(101); // false, over 100

Currency

TF.Currency (builder TF.currency()) sets the isCurrency param on TF.Number. Validation and the JSON round trip work like TF.Number. Friendly error messages show a broken limit with the currency symbol and decimals of the reader's language.

type Balance = TF.Currency<{min: 0}>;
const isBalance = createValidateFn<Balance>();

isBalance(120.5); // true, checked like any number
Copyright © 2026