Number & BigInt
The Number and BigInt modules add named, pipeable operations around plain
JavaScript numeric values. Numbers stay native numbers (including NaN,
Infinity, and floating-point behavior) and bigints stay native bigints — the
modules do not introduce wrapper types. What they add is a consistent surface
for arithmetic, comparisons, range checks, parsing, conversion, and aggregation.
import { Number, pipe } from "effect"
// Pipeable arithmeticconst result = pipe( 10, Number.sum(5), // 15 Number.multiply(2), // 30 Number.subtract(6) // 24)console.log(result) // => 24The safety story
Section titled “The safety story”The central design choice in both modules: operations that could produce NaN,
Infinity, throw, or silently lose precision instead return an
Option. Each has an *Unsafe counterpart for when you
already know the input is valid (and want the raw value or a thrown error).
import { Number, BigInt } from "effect"
// Safe — never produces NaN/Infinity, surfaces failure as Option.none()Number.divide(6, 0) // => Option.none()Number.parse("not a number") // => Option.none()BigInt.fromString("a") // => Option.none()BigInt.fromNumber(1.5) // => Option.none() (not an integer)BigInt.toNumber(BigInt(Number.MAX_SAFE_INTEGER) + 1n) // => Option.none() (precision loss)BigInt.sqrt(-1n) // => Option.none()
// Unsafe — assumes valid input, throws on failureNumber.divideUnsafe(6, 3) // => 2BigInt.divideUnsafe(6n, 3n) // => 2nBigInt.sqrtUnsafe(16n) // => 4nThis pairing means you choose your error model explicitly: thread an Option
through the happy path, or assert validity with the *Unsafe variant.
Dual signatures
Section titled “Dual signatures”Almost every binary operation in both modules is dual: you can call it
data-first (Number.sum(2, 3)) or data-last for use in a pipe
(Number.sum(3) returns a function awaiting the value). See
Dual APIs for the full convention.
import { Number, pipe } from "effect"
Number.sum(2, 3) // => 5 (data-first)pipe(2, Number.sum(3)) // => 5 (data-last)Number
Section titled “Number”import { Number } from "effect"Guards & instances
Section titled “Guards & instances”Number
Section titled “Number”The native JavaScript Number constructor, re-exported on the namespace.
Follows native coercion rules — empty strings become 0, invalid strings
become NaN. For safe parsing prefer parse.
import { Number as N } from "effect"
N.Number("42") // => 42N.Number("3.14") // => 3.14N.Number("") // => 0isNumber
Section titled “isNumber”Type guard that narrows an unknown value to number.
import { Number } from "effect"
Number.isNumber(2) // => trueNumber.isNumber("2") // => falseOrder instance for numbers, returning -1 | 0 | 1. Use it
with sorting and comparison APIs that accept an ordering.
import { Number } from "effect"
Number.Order(1, 2) // => -1Number.Order(2, 1) // => 1Number.Order(1, 1) // => 0Equivalence
Section titled “Equivalence”Equivalence instance for numbers. Unlike ===, it
treats NaN as equivalent to NaN.
import { Number } from "effect"
Number.Equivalence(1, 1) // => trueNumber.Equivalence(1, 2) // => falseNumber.Equivalence(NaN, NaN) // => trueArithmetic
Section titled “Arithmetic”Adds two numbers (dual).
import { Number } from "effect"
Number.sum(2, 3) // => 5multiply
Section titled “multiply”Multiplies two numbers (dual).
import { Number } from "effect"
Number.multiply(2, 3) // => 6subtract
Section titled “subtract”Subtracts the second number from the first (dual).
import { Number } from "effect"
Number.subtract(2, 3) // => -1divide
Section titled “divide”Safe division returning Option.none() only when the divisor is 0 (dual).
Other JavaScript results, including NaN, still follow normal number semantics.
import { Number } from "effect"
Number.divide(6, 3) // => Option.some(2)Number.divide(6, 0) // => Option.none()divideUnsafe
Section titled “divideUnsafe”Division that throws a RangeError("Division by zero") when the divisor is 0
(dual). Use when the divisor is known to be non-zero.
import { Number } from "effect"
Number.divideUnsafe(6, 3) // => 2// Number.divideUnsafe(6, 0) throws RangeError("Division by zero")increment
Section titled “increment”Adds 1 to a number.
import { Number } from "effect"
Number.increment(2) // => 3decrement
Section titled “decrement”Subtracts 1 from a number.
import { Number } from "effect"
Number.decrement(3) // => 2remainder
Section titled “remainder”Returns the remainder of dividing the first operand by the second, taking the
sign of the dividend (dual). Preserves decimal precision better than the raw
JavaScript % operator for decimal operands.
import { Number } from "effect"
Number.remainder(2, 2) // => 0Number.remainder(3, 2) // => 1Number.remainder(-4, 2) // => -0Classifies a number as negative (-1), zero (0), or positive (1).
import { Number } from "effect"
Number.sign(-5) // => -1Number.sign(0) // => 0Number.sign(5) // => 1Rounds a number to the given number of decimal places (dual).
import { Number } from "effect"
Number.round(1.1234, 2) // => 1.12Number.round(1.567, 2) // => 1.57nextPow2
Section titled “nextPow2”Rounds a number up to the next power of two (minimum 2).
import { Number } from "effect"
Number.nextPow2(5) // => 8Number.nextPow2(17) // => 32Comparison & range
Section titled “Comparison & range”isLessThan
Section titled “isLessThan”true if the first argument is strictly less than the second (dual).
import { Number } from "effect"
Number.isLessThan(2, 3) // => trueNumber.isLessThan(3, 3) // => falseisLessThanOrEqualTo
Section titled “isLessThanOrEqualTo”true if the first argument is less than or equal to the second (dual).
import { Number } from "effect"
Number.isLessThanOrEqualTo(3, 3) // => trueNumber.isLessThanOrEqualTo(4, 3) // => falseisGreaterThan
Section titled “isGreaterThan”true if the first argument is strictly greater than the second (dual).
import { Number } from "effect"
Number.isGreaterThan(4, 3) // => trueNumber.isGreaterThan(3, 3) // => falseisGreaterThanOrEqualTo
Section titled “isGreaterThanOrEqualTo”true if the first argument is greater than or equal to the second (dual).
import { Number } from "effect"
Number.isGreaterThanOrEqualTo(3, 3) // => trueNumber.isGreaterThanOrEqualTo(2, 3) // => falsebetween
Section titled “between”Checks whether a number falls inside an inclusive [minimum, maximum] range
(dual).
import { Number } from "effect"
const between = Number.between({ minimum: 0, maximum: 5 })
between(3) // => truebetween(-1) // => falsebetween(6) // => falseForces a number into an inclusive [minimum, maximum] range, returning the
boundary when out of range (dual).
import { Number } from "effect"
const clamp = Number.clamp({ minimum: 1, maximum: 5 })
clamp(3) // => 3clamp(0) // => 1clamp(6) // => 5Returns the smaller of two numbers (dual).
import { Number } from "effect"
Number.min(2, 3) // => 2Returns the larger of two numbers (dual).
import { Number } from "effect"
Number.max(2, 3) // => 3Parsing
Section titled “Parsing”Parses a number from a string without throwing, returning Option<number>. The
strings "NaN", "Infinity", and "-Infinity" are supported; blank or invalid
text yields Option.none().
import { Number } from "effect"
Number.parse("42") // => Option.some(42)Number.parse("3.14") // => Option.some(3.14)Number.parse("Infinity") // => Option.some(Infinity)Number.parse("not a number") // => Option.none()Number.parse("") // => Option.none()Aggregation
Section titled “Aggregation”sumAll
Section titled “sumAll”Sums an iterable of numbers. Returns 0 for an empty iterable.
import { Number } from "effect"
Number.sumAll([2, 3, 4]) // => 9multiplyAll
Section titled “multiplyAll”Multiplies an iterable of numbers. Returns 1 for an empty iterable, and
short-circuits to 0 as soon as it sees a 0.
import { Number } from "effect"
Number.multiplyAll([2, 3, 4]) // => 24Reducers
Section titled “Reducers”A Reducer packages a binary combine operation together with an identity
value (and an optional optimized combineAll). It is the abstraction Effect
collection APIs consume when they need to fold values. You can use one directly
via reducer.combineAll(iterable), which folds starting from the identity — so
an empty collection returns the identity rather than failing.
import { Number } from "effect"
// combineAll folds an iterable from the reducer's identityNumber.ReducerSum.combineAll([1, 2, 3]) // => 6Number.ReducerSum.combineAll([]) // => 0 (identity)
// combine merges two values directlyNumber.ReducerSum.combine(4, 5) // => 9ReducerSum
Section titled “ReducerSum”Combines numbers with addition; identity 0.
import { Number } from "effect"
Number.ReducerSum.combineAll([10, 20, 30]) // => 60Number.ReducerSum.combineAll([]) // => 0ReducerMultiply
Section titled “ReducerMultiply”Combines numbers with multiplication; identity 1. Short-circuits to 0 when
it encounters a 0.
import { Number } from "effect"
Number.ReducerMultiply.combineAll([2, 3, 4]) // => 24Number.ReducerMultiply.combineAll([]) // => 1ReducerMax
Section titled “ReducerMax”Keeps the maximum value; identity -Infinity (so an empty collection returns
-Infinity). NaN propagates through Math.max.
import { Number } from "effect"
Number.ReducerMax.combineAll([3, 1, 4, 1, 5]) // => 5Number.ReducerMax.combineAll([]) // => -InfinityReducerMin
Section titled “ReducerMin”Keeps the minimum value; identity Infinity (so an empty collection returns
Infinity). NaN propagates through Math.min.
import { Number } from "effect"
Number.ReducerMin.combineAll([3, 1, 4, 1, 5]) // => 1Number.ReducerMin.combineAll([]) // => InfinityBigInt
Section titled “BigInt”import { BigInt } from "effect"Reach for BigInt when values may exceed JavaScript’s safe integer range, when
conversions should make failure explicit with Option, or when collection APIs
need bigint-specific ordering or combining. Use the n literal suffix for
bigint values (10n).
Guards & instances
Section titled “Guards & instances”BigInt
Section titled “BigInt”The native BigInt constructor, re-exported on the namespace. Follows native
coercion — it throws for invalid strings or non-integral numbers, and
whitespace-only strings coerce to 0n. For safe conversion prefer
fromString / fromNumber.
import { BigInt } from "effect"
BigInt.BigInt(123) // => 123nBigInt.BigInt("456") // => 456nisBigInt
Section titled “isBigInt”Type guard that narrows an unknown value to bigint.
import { BigInt } from "effect"
BigInt.isBigInt(1n) // => trueBigInt.isBigInt(1) // => falseOrder instance for bigints.
import { BigInt } from "effect"
BigInt.Order(123n, 456n) // => -1BigInt.Order(456n, 123n) // => 1BigInt.Order(123n, 123n) // => 0Equivalence
Section titled “Equivalence”Equivalence instance for bigints, using strict
equality.
import { BigInt } from "effect"
BigInt.Equivalence(1n, 1n) // => trueBigInt.Equivalence(1n, 2n) // => falseArithmetic
Section titled “Arithmetic”Adds two bigints (dual).
import { BigInt } from "effect"
BigInt.sum(2n, 3n) // => 5nmultiply
Section titled “multiply”Multiplies two bigints (dual).
import { BigInt } from "effect"
BigInt.multiply(2n, 3n) // => 6nsubtract
Section titled “subtract”Subtracts the second bigint from the first (dual).
import { BigInt } from "effect"
BigInt.subtract(2n, 3n) // => -1ndivide
Section titled “divide”Safe division returning Option.none() when the divisor is 0n (dual).
Non-exact quotients truncate toward zero.
import { BigInt } from "effect"
BigInt.divide(6n, 3n) // => Option.some(2n)BigInt.divide(6n, 0n) // => Option.none()divideUnsafe
Section titled “divideUnsafe”Division that throws when the divisor is 0n (dual). Truncates toward zero.
import { BigInt } from "effect"
BigInt.divideUnsafe(6n, 3n) // => 2nBigInt.divideUnsafe(6n, 4n) // => 1n (truncated toward zero)increment
Section titled “increment”Adds 1n to a bigint.
import { BigInt } from "effect"
BigInt.increment(2n) // => 3ndecrement
Section titled “decrement”Subtracts 1n from a bigint.
import { BigInt } from "effect"
BigInt.decrement(3n) // => 2nremainder
Section titled “remainder”Returns the JavaScript % remainder (sign of the dividend), throwing when the
divisor is 0n (dual).
import { BigInt } from "effect"
BigInt.remainder(10n, 3n) // => 1nBigInt.remainder(15n, 4n) // => 3nClassifies a bigint as negative (-1), zero (0), or positive (1).
import { BigInt } from "effect"
BigInt.sign(-5n) // => -1BigInt.sign(0n) // => 0BigInt.sign(5n) // => 1Returns the absolute value (magnitude with sign removed).
import { BigInt } from "effect"
BigInt.abs(-5n) // => 5nBigInt.abs(5n) // => 5nGreatest common divisor of two bigints (dual).
import { BigInt } from "effect"
BigInt.gcd(2n, 3n) // => 1nBigInt.gcd(16n, 24n) // => 8nLeast common multiple of two bigints (dual).
import { BigInt } from "effect"
BigInt.lcm(2n, 3n) // => 6nBigInt.lcm(16n, 24n) // => 48nSafe integer square root returning Option<bigint>; Option.none() for
negative input. For non-perfect squares, returns the largest bigint whose square
is <= the input.
import { BigInt } from "effect"
BigInt.sqrt(16n) // => Option.some(4n)BigInt.sqrt(10n) // => Option.some(3n)BigInt.sqrt(-1n) // => Option.none()sqrtUnsafe
Section titled “sqrtUnsafe”Integer square root that throws a RangeError on negative input. Use when the
input is known to be non-negative.
import { BigInt } from "effect"
BigInt.sqrtUnsafe(4n) // => 2nBigInt.sqrtUnsafe(9n) // => 3n// BigInt.sqrtUnsafe(-1n) throws RangeErrorComparison & range
Section titled “Comparison & range”isLessThan
Section titled “isLessThan”true if the first argument is strictly less than the second (dual).
import { BigInt } from "effect"
BigInt.isLessThan(2n, 3n) // => trueBigInt.isLessThan(3n, 3n) // => falseisLessThanOrEqualTo
Section titled “isLessThanOrEqualTo”true if the first argument is less than or equal to the second (dual).
import { BigInt } from "effect"
BigInt.isLessThanOrEqualTo(3n, 3n) // => trueBigInt.isLessThanOrEqualTo(4n, 3n) // => falseisGreaterThan
Section titled “isGreaterThan”true if the first argument is strictly greater than the second (dual).
import { BigInt } from "effect"
BigInt.isGreaterThan(4n, 3n) // => trueBigInt.isGreaterThan(3n, 3n) // => falseisGreaterThanOrEqualTo
Section titled “isGreaterThanOrEqualTo”true if the first argument is greater than or equal to the second (dual).
import { BigInt } from "effect"
BigInt.isGreaterThanOrEqualTo(3n, 3n) // => trueBigInt.isGreaterThanOrEqualTo(2n, 3n) // => falsebetween
Section titled “between”Checks whether a bigint falls inside an inclusive [minimum, maximum] range
(dual).
import { BigInt } from "effect"
const between = BigInt.between({ minimum: 0n, maximum: 5n })
between(3n) // => truebetween(-1n) // => falsebetween(6n) // => falseForces a bigint into an inclusive [minimum, maximum] range (dual).
import { BigInt } from "effect"
const clamp = BigInt.clamp({ minimum: 1n, maximum: 5n })
clamp(3n) // => 3nclamp(0n) // => 1nclamp(6n) // => 5nReturns the smaller of two bigints (dual).
import { BigInt } from "effect"
BigInt.min(2n, 3n) // => 2nReturns the larger of two bigints (dual).
import { BigInt } from "effect"
BigInt.max(2n, 3n) // => 3nConversion
Section titled “Conversion”toNumber
Section titled “toNumber”Converts a bigint to a number safely, returning Option.none() when the value
falls outside the safe integer range (guarding against precision loss).
import { BigInt as BI } from "effect"
BI.toNumber(42n) // => Option.some(42)BI.toNumber(BigInt(Number.MAX_SAFE_INTEGER) + 1n) // => Option.none()fromString
Section titled “fromString”Parses a string into a bigint safely, returning Option.none() for empty or
invalid input (rather than throwing like the native constructor).
import { BigInt } from "effect"
BigInt.fromString("42") // => Option.some(42n)BigInt.fromString(" ") // => Option.none()BigInt.fromString("a") // => Option.none()fromNumber
Section titled “fromNumber”Converts a number to a bigint safely, returning Option.none() for
non-integers or values outside the safe integer range.
import { BigInt } from "effect"
BigInt.fromNumber(42) // => Option.some(42n)BigInt.fromNumber(1.5) // => Option.none() (not an integer)BigInt.fromNumber(Number.MAX_SAFE_INTEGER + 1) // => Option.none()Aggregation
Section titled “Aggregation”sumAll
Section titled “sumAll”Sums an iterable of bigints. Returns 0n for an empty iterable.
import { BigInt } from "effect"
BigInt.sumAll([2n, 3n, 4n]) // => 9nmultiplyAll
Section titled “multiplyAll”Multiplies an iterable of bigints. Returns 1n for an empty iterable, and
short-circuits to 0n as soon as it sees a 0n.
import { BigInt } from "effect"
BigInt.multiplyAll([2n, 3n, 4n]) // => 24nReducers
Section titled “Reducers”Like the Number reducers, these Reducer instances carry an identity value
and expose combineAll for folding an iterable (empty iterable returns the
identity).
ReducerSum
Section titled “ReducerSum”Combines bigints with addition; identity 0n.
import { BigInt } from "effect"
BigInt.ReducerSum.combineAll([10n, 20n, 30n]) // => 60nBigInt.ReducerSum.combineAll([]) // => 0nReducerMultiply
Section titled “ReducerMultiply”Combines bigints with multiplication; identity 1n. Short-circuits to 0n when
it encounters a 0n.
import { BigInt } from "effect"
BigInt.ReducerMultiply.combineAll([2n, 3n, 4n]) // => 24nBigInt.ReducerMultiply.combineAll([]) // => 1nCombiners
Section titled “Combiners”A Combiner is the identity-free cousin of a Reducer: it carries only a
binary combine operation, so there is no identity value and no combineAll.
Use one to merge two values where no neutral element exists (here, max/min).
CombinerMax
Section titled “CombinerMax”Returns the larger of two bigints.
import { BigInt } from "effect"
BigInt.CombinerMax.combine(2n, 5n) // => 5nCombinerMin
Section titled “CombinerMin”Returns the smaller of two bigints.
import { BigInt } from "effect"
BigInt.CombinerMin.combine(2n, 5n) // => 2n