Number.ts overview
Extension to the effect/Number module providing safe conversions from bigint and BigDecimal, positive integer modulo, decimal shifting and truncation, and a few numeric predicates.
Mental model
Typeis justnumber.- Conversions come in
unsafe*(lossy: too-large or non-finite values become±InfinityorNaN) and*Option(validating, returningOption) flavors. - Use
intModulowhen you need a positive modulo (the JavaScript%operator is sign-preserving).
Common tasks
- Convert from
bigint:unsafeFromBigInt,fromBigInt - Convert from
BigDecimal:unsafeFromBigDecimal,fromBigDecimal - Convert from
string:unsafeFromString - Arithmetic:
opposite,intModulo,quotientAndRemainder,shift - Predicates:
equals,isMultipleOf - Sign:
sign2 - Constants:
MAX_SAFE_INTEGER,MIN_SAFE_INTEGER
Quickstart
Example (Safe conversion and positive modulo)
import * as MNumber from "@parischap/effect-lib/MNumber"
console.log(MNumber.fromBigInt(123n)) // Some(123)
console.log(MNumber.intModulo(3)(-7)) // 2 (vs. -7 % 3 === -1)
Exports Grouped by Category
Constructors
fromBigDecimal
Builds a number from a BigDecimal, returning Option.some when the input lies in [Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER] and Option.none otherwise.
See
unsafeFromBigDecimal— unchecked variant
Signature
declare const fromBigDecimal: MTypes.OneArgFunction<BigDecimal.BigDecimal, Option.Option<number>>
fromBigInt
Builds a number from a bigint, returning Option.some when the input lies in [Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER] and Option.none otherwise.
Example (Safe conversion)
import * as MNumber from "@parischap/effect-lib/MNumber"
console.log(MNumber.fromBigInt(42n)) // Some(42)
console.log(MNumber.fromBigInt(2n ** 100n)) // None
See
unsafeFromBigInt— unchecked variant
Signature
declare const fromBigInt: MTypes.OneArgFunction<bigint, Option.Option<number>>
fromFormatAndString
Returns a function that tries to convert a whole string into a number respecting format. Unlike fromFormatAndStringStart, the whole of the input string must represent a number.
- Use a precomputed parser when the same
formatwill be applied many times.
Example (Parse a number from a whole string)
import * as MNumber from "@parischap/effect-lib/MNumber"
import * as MNumberBase10Format from "@parischap/effect-lib/MNumberBase10Format"
const parse = MNumber.fromFormatAndString(MNumberBase10Format.frenchStyleNumber)
console.log(parse("-45,50")) // Some(-45.5)
console.log(parse("-45,50Dummy")) // None
Signature
declare const fromFormatAndString: (
format: MNumberBase10Format.Type
) => MTypes.OneArgFunction<string, Option.Option<number>>
fromFormatAndStringOrThrow
Same as fromFormatAndString but throws in case of failure
Signature
declare const fromFormatAndStringOrThrow: (format: MNumberBase10Format.Type) => MTypes.OneArgFunction<string, number>
fromFormatAndStringStart
Returns a function that tries to extract, from the start of a string, a number respecting format. If successful, returns a some of a [value, match] pair where match is the part of the string that could be analyzed as representing a number. Otherwise, returns a none. Unlike BigDecimal, number distinguishes -0 from 0.
- Use a precomputed extractor when the same
formatwill be applied many times.
Example (Extract a number from the start of a string)
import * as MNumber from "@parischap/effect-lib/MNumber"
import * as MNumberBase10Format from "@parischap/effect-lib/MNumberBase10Format"
const extract = MNumber.fromFormatAndStringStart(MNumberBase10Format.frenchStyleNumber)
console.log(extract("-45,50Dummy")) // Some([-45.5, '-45,50'])
Signature
declare const fromFormatAndStringStart: (
format: MNumberBase10Format.Type
) => MTypes.OneArgFunction<string, Option.Option<[value: number, match: string]>>
fromFormatAndStringStartOrThrow
Same as fromFormatAndStringStart but throws in case of failure
Signature
declare const fromFormatAndStringStartOrThrow: (
format: MNumberBase10Format.Type
) => MTypes.OneArgFunction<string, [value: number, match: string]>
unsafeFromBigDecimal
Builds a number from a BigDecimal without range checks. Values outside the safe-integer range are coerced to ±Infinity.
See
fromBigDecimal— safe variant
Signature
declare const unsafeFromBigDecimal: MTypes.OneArgFunction<BigDecimal.BigDecimal, number>
unsafeFromBigInt
Builds a number from a bigint without range checks. Values outside the safe-integer range are coerced to ±Infinity.
- Use only when the input is statically known to fit in a JavaScript
number.
Example (Lossy conversion)
import * as MNumber from "@parischap/effect-lib/MNumber"
console.log(MNumber.unsafeFromBigInt(42n)) // 42
console.log(MNumber.unsafeFromBigInt(2n ** 100n)) // Infinity
See
fromBigInt— safe variant
Signature
declare const unsafeFromBigInt: MTypes.OneArgFunction<bigint, number>
unsafeFromString
Builds a number from a string. Returns NaN when the string is not a valid numeric literal.
'Infinity'/'+Infinity'produceInfinity;'-Infinity'produces-Infinity.
Example (String to number)
import * as MNumber from "@parischap/effect-lib/MNumber"
console.log(MNumber.unsafeFromString("42")) // 42
console.log(MNumber.unsafeFromString("abc")) // NaN
Signature
declare const unsafeFromString: MTypes.NumberFromString
Destructors
quotientAndRemainder
Returns [quotient, remainder] for the Euclidean division of self by divisor. The remainder carries the sign of divisor.
- Both inputs must be finite integers; otherwise the result is meaningless.
Example (Quotient and remainder)
import { pipe } from "effect"
import * as MNumber from "@parischap/effect-lib/MNumber"
console.log(pipe(7, MNumber.quotientAndRemainder(3))) // [2, 1]
console.log(pipe(-7, MNumber.quotientAndRemainder(3))) // [-3, 2]
Signature
declare const quotientAndRemainder: (divisor: number) => (self: Type) => [quotient: number, remainder: number]
Models
Type (type alias)
Type on which this module’s functions operate.
Signature
type Type = number
Predicates
equals
Returns true when self and n differ by less than Number.EPSILON.
- Use to compare floating-point numbers where exact
===is unreliable. - This is an absolute, not relative, tolerance — it is not appropriate for very large magnitudes.
Example (Floating-point equality)
import { pipe } from "effect"
import * as MNumber from "@parischap/effect-lib/MNumber"
console.log(pipe(0.1 + 0.2, MNumber.equals(0.3))) // true
Signature
declare const equals: (n: number) => Predicate.Predicate<Type>
isMultipleOf
Returns true when self is a multiple of a.
- Works for any signs of
selfanda.
Example (Multiplicity check)
import { pipe } from "effect"
import * as MNumber from "@parischap/effect-lib/MNumber"
console.log(pipe(10, MNumber.isMultipleOf(2))) // true
console.log(pipe(-9, MNumber.isMultipleOf(3))) // true
Signature
declare const isMultipleOf: (a: number) => Predicate.Predicate<Type>
Utils
intModulo
Returns the non-negative remainder of the integer division of self by divisor.
- Use when a positive remainder is needed (the built-in
%preserves the sign ofself). - Both inputs must be finite integers; otherwise the result is meaningless.
Example (Positive integer modulo)
import { pipe } from "effect"
import * as MNumber from "@parischap/effect-lib/MNumber"
console.log(pipe(-7, MNumber.intModulo(3))) // 2
console.log(pipe(7, MNumber.intModulo(3))) // 1
Signature
declare const intModulo: (divisor: number) => MTypes.OneArgFunction<Type>
opposite
Returns the additive inverse of self (i.e. -self).
Example (Negation)
import * as MNumber from "@parischap/effect-lib/MNumber"
console.log(MNumber.opposite(3)) // -3
console.log(MNumber.opposite(-3)) // 3
Signature
declare const opposite: (self: Type) => number
round
Returns a function that rounds self to precision decimal digits according to option.
- Use a precomputed rounder when the same
precision/optionpair will be applied many times.
Example (Round to three decimal digits, half to even)
import { pipe } from "effect"
import * as MNumber from "@parischap/effect-lib/MNumber"
import * as MNumberBase10Format from "@parischap/effect-lib/MNumberBase10Format"
const round = MNumber.round(3, MNumberBase10Format.RoundingOption.HalfEven)
console.log(pipe(12.4565, round)) // 12.456
Signature
declare const round: (precision: number, option: MNumberBase10Format.RoundingOption) => MTypes.OneArgFunction<Type>
shift
Multiplies self by 10^n (i.e. shifts the decimal point by n positions).
- Use as the building block of decimal-aware truncation/rounding.
Example (Decimal shift)
import { pipe } from "effect"
import * as MNumber from "@parischap/effect-lib/MNumber"
console.log(pipe(1.5, MNumber.shift(2))) // 150
console.log(pipe(150, MNumber.shift(-2))) // 1.5
Signature
declare const shift: (n: number) => (self: Type) => number
sign2
Returns the sign of n as either 1 or -1. Treats +0 (and the unsigned literal 0) as positive and -0 as negative.
- Differs from
Math.sign, which returns0/-0for those inputs.
Example (Sign with ±0 distinction)
import * as MNumber from "@parischap/effect-lib/MNumber"
console.log(MNumber.sign2(3)) // 1
console.log(MNumber.sign2(-3)) // -1
console.log(MNumber.sign2(0)) // 1
console.log(MNumber.sign2(-0)) // -1
Signature
declare const sign2: (n: number) => 1 | -1