Math and Bigint
The math category performs arithmetic in the type system. Every operation accepts number or bigint,
supports negative and floating point values, and coerces between number and bigint when a result
cannot be represented in the input’s type.
The bigint category holds the identity and cast utilities for bigint itself.
The Fail parameter
Section titled “The Fail parameter”Every math type takes a third type parameter, Fail, defaulting to never:
type Add<A extends number | bigint, B extends number | bigint, Fail = never>Fail is returned when the operation cannot be computed — most commonly when an input is the wide
number or bigint type instead of a literal. Supply your own value to distinguish a failure from a
legitimate never result.
type R1 = Add<1, 2> // 3type R2 = Add<number, 2> // nevertype R3 = Add<number, 2, 'fail'> // 'fail'Internally the operands are converted into a NumericStruct — a sign, digit tuple and exponent, similar
to a floating point representation — operated on, then converted back. That machinery lives in
numeric_struct.ts and is not part of the public API.
Add and Increment
Section titled “Add and Increment”type Add<A extends number | bigint, B extends number | bigint, Fail = never>type Increment<N extends number | bigint> // Add<N, 1>type R1 = Add<1, 2> // 3type R2 = Add<1.2, -2> // -0.8type R3 = Add<1n, 2.3> // 3.3, coerced to numbertype R4 = Add<9007199254740992, 1> // 9007199254740993n, coerced to biginttype R5 = Increment<41> // 42Subtract and Decrement
Section titled “Subtract and Decrement”type Subtract<A extends number | bigint, B extends number | bigint, Fail = never>type Decrement<N extends number | bigint> // Subtract<N, 1>type R1 = Subtract<100, 2> // 98type R2 = Subtract<1.2, 2> // -0.8type R3 = Subtract<1n, 2.3> // -1.3, coerced to numbertype R4 = Decrement<1> // 0Multiply
Section titled “Multiply”type Multiply<A extends number | bigint, B extends number | bigint, Fail = never>type R1 = Multiply<100, 2> // 200type R2 = Multiply<1.2, 2> // 2.4type R3 = Multiply<1n, 2.3> // 2.3, coerced to numberGreaterThan and Max
Section titled “GreaterThan and Max”type GreaterThan<A extends number | bigint, B extends number | bigint, Fail = never>type Max<A extends number | bigint, B extends number | bigint, Fail = never>GreaterThan performs A > B. Max returns whichever of A or B is larger.
type R1 = GreaterThan<100, 2> // truetype R2 = GreaterThan<1.2, 2> // falsetype R3 = Max<-1, 2> // 2type R4 = Max<1.2, 2> // 2type Abs<N extends number | bigint, Fail = never>The absolute value of N. Returns Fail for the wide number and bigint types.
type R1 = Abs<-5> // 5type R2 = Abs<5> // 5type R3 = Abs<-1n> // 1ntype R4 = Abs<number> // neverMathPlus.ToNegative
Section titled “MathPlus.ToNegative”type ToNegative<N extends number | bigint>ToNegative is exported only through the MathPlus namespace. It converts N to negative, and returns
N unchanged if it is already negative or zero.
import type { MathPlus } from 'type-plus'
type R1 = MathPlus.ToNegative<5> // -5type R2 = MathPlus.ToNegative<0> // 0type R3 = MathPlus.ToNegative<-5> // -5MathPlus also re-exports Add, Increment, Subtract, Decrement and Multiply, so
MathPlus.Add<1, 2> and Add<1, 2> are the same type.
IsBigint and IsNotBigint
Section titled “IsBigint and IsNotBigint”type IsBigint<T, $O extends IsBigint.$Options = {}>type IsNotBigint<T, $O extends IsNotBigint.$Options = {}>🎭 predicate — is T bigint or a bigint literal.
type R1 = IsBigint<bigint> // truetype R2 = IsBigint<1n> // truetype R3 = IsBigint<string | boolean> // falsetype R4 = IsBigint<string | bigint> // boolean, distributedtype R5 = IsNotBigint<1n> // falseBoth support selection: 'filter', exact: true, distributive: false, and the $any / $unknown /
$never / $void branch overrides. See type branching.
type R6 = IsBigint<1n, { exact: true }> // false — `1n` is not exactly `bigint`type R7 = IsBigint<1n, { selection: 'filter' }> // 1ntype R8 = IsBigint<string | bigint, { distributive: false }> // falseIsBigintLiteral and IsNotBigintLiteral
Section titled “IsBigintLiteral and IsNotBigintLiteral”type IsBigintLiteral<T, $O extends IsBigintLiteral.$Options = {}>type IsNotBigintLiteral<T, $O extends IsNotBigintLiteral.$Options = {}>Narrower than IsBigint: only bigint literals pass.
type R1 = IsBigintLiteral<1n> // truetype R2 = IsBigintLiteral<bigint> // falsetype R3 = IsNotBigintLiteral<bigint> // truetype R4 = IsNotBigintLiteral<1n | string, { selection: 'filter' }> // stringStringToBigint
Section titled “StringToBigint”type StringToBigint<S extends string, Fail = never>Casts a string literal to a bigint literal when the string is a valid bigint form.
type R1 = StringToBigint<'1n'> // 1ntype R2 = StringToBigint<'-1n'> // -1ntype R3 = StringToBigint<'abc'> // never