Pure-JavaScript implementation of ECMAScript BigInt for arbitrary-precision integer arithmetic.
npx @tessl/cli install tessl/npm-jsbi@4.3.0JSBI is a pure-JavaScript implementation of the ECMAScript BigInt proposal, providing arbitrary-precision integer arithmetic that behaves exactly like native BigInts. It enables BigInt functionality in environments that don't support native BigInts and can be mechanically transpiled to native BigInt code when available.
npm install jsbiimport JSBI from "jsbi";For CommonJS:
const JSBI = require("jsbi");For ES modules (browser):
import JSBI from "./jsbi.mjs";import JSBI from "jsbi";
// Create BigInt-like values from various types
const max = JSBI.BigInt(Number.MAX_SAFE_INTEGER);
const fromString = JSBI.BigInt("123456789012345678901234567890");
const two = JSBI.BigInt(2);
// Perform arithmetic operations
const sum = JSBI.add(max, two);
const product = JSBI.multiply(fromString, two);
const quotient = JSBI.divide(fromString, two);
// Convert back to string/number
console.log(sum.toString()); // "9007199254740993"
console.log(JSBI.toNumber(two)); // 2
// Comparisons
const isLess = JSBI.lessThan(two, max); // true
const areEqual = JSBI.equal(two, JSBI.BigInt(2)); // true
// Bitwise operations
const shifted = JSBI.leftShift(two, JSBI.BigInt(3)); // 16
const anded = JSBI.bitwiseAnd(fromString, JSBI.BigInt(255));JSBI is implemented as a single class extending Array that provides all BigInt operations through static methods:
JSBI.methodName()Create JSBI instances from various input types and convert back to JavaScript primitives.
/**
* Creates a JSBI instance from number, string, boolean, or object
* @param arg - Input value to convert to BigInt
* @returns JSBI instance representing the BigInt value
* @throws RangeError for non-integer numbers or numbers outside safe range
* @throws SyntaxError for invalid string inputs
* @throws TypeError for unconvertible object inputs
*/
static BigInt(arg: number | string | boolean | object): JSBI;
/**
* Converts JSBI instance to JavaScript number (may lose precision)
* @param x - JSBI instance to convert
* @returns JavaScript number representation
*/
static toNumber(x: JSBI): number;
/**
* Converts JSBI to string representation in specified radix
* @param radix - Base for string conversion (2-36), defaults to 10
* @returns String representation of the BigInt value
* @throws RangeError if radix is outside valid range
*/
toString(radix?: number): string;
/**
* Returns debug representation showing internal digit structure
* @returns Debug string with internal representation
*/
toDebugString(): string;
/**
* Intentionally throws error to prevent accidental coercion
* @throws Error with guidance to use toNumber() instead
*/
valueOf(): void;Fundamental arithmetic operations for BigInt values.
/**
* Returns the negation of x (-x)
* @param x - JSBI instance to negate
* @returns New JSBI instance with opposite sign
*/
static unaryMinus(x: JSBI): JSBI;
/**
* Returns sum of x and y (x + y)
* @param x - First operand
* @param y - Second operand
* @returns New JSBI instance with the sum
*/
static add(x: JSBI, y: JSBI): JSBI;
/**
* Returns difference of x and y (x - y)
* @param x - Minuend
* @param y - Subtrahend
* @returns New JSBI instance with the difference
*/
static subtract(x: JSBI, y: JSBI): JSBI;
/**
* Returns product of x and y (x * y)
* @param x - Multiplicand
* @param y - Multiplier
* @returns New JSBI instance with the product
*/
static multiply(x: JSBI, y: JSBI): JSBI;
/**
* Returns quotient of x divided by y (x / y)
* @param x - Dividend
* @param y - Divisor
* @returns New JSBI instance with the quotient
* @throws RangeError if y is zero
*/
static divide(x: JSBI, y: JSBI): JSBI;
/**
* Returns remainder of x divided by y (x % y)
* @param x - Dividend
* @param y - Divisor
* @returns New JSBI instance with the remainder
* @throws RangeError if y is zero
*/
static remainder(x: JSBI, y: JSBI): JSBI;
/**
* Returns x raised to the power of y (x ** y)
* @param x - Base
* @param y - Exponent (must be non-negative)
* @returns New JSBI instance with the result
* @throws RangeError if y is negative or result would be too large
*/
static exponentiate(x: JSBI, y: JSBI): JSBI;Bitwise manipulation operations following BigInt semantics.
/**
* Returns bitwise NOT of x (~x)
* @param x - JSBI instance to invert
* @returns New JSBI instance with all bits flipped
*/
static bitwiseNot(x: JSBI): JSBI;
/**
* Returns bitwise AND of x and y (x & y)
* @param x - First operand
* @param y - Second operand
* @returns New JSBI instance with bitwise AND result
*/
static bitwiseAnd(x: JSBI, y: JSBI): JSBI;
/**
* Returns bitwise OR of x and y (x | y)
* @param x - First operand
* @param y - Second operand
* @returns New JSBI instance with bitwise OR result
*/
static bitwiseOr(x: JSBI, y: JSBI): JSBI;
/**
* Returns bitwise XOR of x and y (x ^ y)
* @param x - First operand
* @param y - Second operand
* @returns New JSBI instance with bitwise XOR result
*/
static bitwiseXor(x: JSBI, y: JSBI): JSBI;
/**
* Returns x left-shifted by y bits (x << y)
* @param x - Value to shift
* @param y - Number of bit positions to shift (negative shifts right)
* @returns New JSBI instance with shifted value
* @throws RangeError if shift amount is too large
*/
static leftShift(x: JSBI, y: JSBI): JSBI;
/**
* Returns x right-shifted by y bits with sign extension (x >> y)
* @param x - Value to shift
* @param y - Number of bit positions to shift (negative shifts left)
* @returns New JSBI instance with shifted value
* @throws RangeError if shift amount is too large
*/
static signedRightShift(x: JSBI, y: JSBI): JSBI;
/**
* Intentionally throws error as BigInt has no unsigned right shift
* @throws TypeError indicating BigInts don't support unsigned right shift
*/
static unsignedRightShift(): void;Comparison operations returning boolean results.
/**
* Returns true if x < y
* @param x - First operand
* @param y - Second operand
* @returns Boolean result of comparison
*/
static lessThan(x: JSBI, y: JSBI): boolean;
/**
* Returns true if x <= y
* @param x - First operand
* @param y - Second operand
* @returns Boolean result of comparison
*/
static lessThanOrEqual(x: JSBI, y: JSBI): boolean;
/**
* Returns true if x > y
* @param x - First operand
* @param y - Second operand
* @returns Boolean result of comparison
*/
static greaterThan(x: JSBI, y: JSBI): boolean;
/**
* Returns true if x >= y
* @param x - First operand
* @param y - Second operand
* @returns Boolean result of comparison
*/
static greaterThanOrEqual(x: JSBI, y: JSBI): boolean;
/**
* Returns true if x equals y
* @param x - First operand
* @param y - Second operand
* @returns Boolean result of equality comparison
*/
static equal(x: JSBI, y: JSBI): boolean;
/**
* Returns true if x does not equal y
* @param x - First operand
* @param y - Second operand
* @returns Boolean result of inequality comparison
*/
static notEqual(x: JSBI, y: JSBI): boolean;Operations for precise bit-level control and two's complement representation.
/**
* Returns x wrapped to n-bit signed integer representation
* @param n - Number of bits for signed representation
* @param x - JSBI instance to wrap
* @returns New JSBI instance wrapped to n-bit signed range
* @throws RangeError if n is negative or not a safe integer
*/
static asIntN(n: number, x: JSBI): JSBI;
/**
* Returns x wrapped to n-bit unsigned integer representation
* @param n - Number of bits for unsigned representation
* @param x - JSBI instance to wrap
* @returns New JSBI instance wrapped to n-bit unsigned range
* @throws RangeError if n is negative, not a safe integer, or result too large
*/
static asUintN(n: number, x: JSBI): JSBI;Type-aware operations that handle mixed JavaScript types with proper coercion.
/**
* Performs type-aware addition with JavaScript type coercion
* @param x - First operand (any type)
* @param y - Second operand (any type)
* @returns String for string concatenation, number for numeric addition, or JSBI for BigInt addition
* @throws TypeError for incompatible type mixing
*/
static ADD(x: any, y: any): string | number | JSBI;
/**
* Type-aware less-than comparison
* @param x - First operand (any type)
* @param y - Second operand (any type)
* @returns Boolean result of comparison
*/
static LT(x: any, y: any): boolean;
/**
* Type-aware less-than-or-equal comparison
* @param x - First operand (any type)
* @param y - Second operand (any type)
* @returns Boolean result of comparison
*/
static LE(x: any, y: any): boolean;
/**
* Type-aware greater-than comparison
* @param x - First operand (any type)
* @param y - Second operand (any type)
* @returns Boolean result of comparison
*/
static GT(x: any, y: any): boolean;
/**
* Type-aware greater-than-or-equal comparison
* @param x - First operand (any type)
* @param y - Second operand (any type)
* @returns Boolean result of comparison
*/
static GE(x: any, y: any): boolean;
/**
* Type-aware equality comparison
* @param x - First operand (any type)
* @param y - Second operand (any type)
* @returns Boolean result of equality comparison
*/
static EQ(x: any, y: any): boolean;
/**
* Type-aware not-equal comparison
* @param x - First operand (any type)
* @param y - Second operand (any type)
* @returns Boolean result of inequality comparison
*/
static NE(x: any, y: any): boolean;Methods for reading and writing BigInt values from/to DataView objects for binary data handling.
/**
* Reads signed 64-bit integer from DataView as JSBI
* @param dataview - DataView to read from
* @param byteOffset - Byte offset within the DataView
* @param littleEndian - Whether to use little-endian byte order, defaults to false
* @returns JSBI instance representing the 64-bit signed integer
*/
static DataViewGetBigInt64(dataview: DataView, byteOffset: number, littleEndian?: boolean): JSBI;
/**
* Reads unsigned 64-bit integer from DataView as JSBI
* @param dataview - DataView to read from
* @param byteOffset - Byte offset within the DataView
* @param littleEndian - Whether to use little-endian byte order, defaults to false
* @returns JSBI instance representing the 64-bit unsigned integer
*/
static DataViewGetBigUint64(dataview: DataView, byteOffset: number, littleEndian?: boolean): JSBI;
/**
* Writes signed 64-bit JSBI value to DataView
* @param dataview - DataView to write to
* @param byteOffset - Byte offset within the DataView
* @param value - JSBI instance to write
* @param littleEndian - Whether to use little-endian byte order, defaults to false
*/
static DataViewSetBigInt64(dataview: DataView, byteOffset: number, value: JSBI, littleEndian?: boolean): void;
/**
* Writes unsigned 64-bit JSBI value to DataView
* @param dataview - DataView to write to
* @param byteOffset - Byte offset within the DataView
* @param value - JSBI instance to write (wrapped to unsigned 64-bit)
* @param littleEndian - Whether to use little-endian byte order, defaults to false
*/
static DataViewSetBigUint64(dataview: DataView, byteOffset: number, value: JSBI, littleEndian?: boolean): void;The main JSBI class extends Array to store BigInt digits internally.
declare class JSBI extends Array {
/**
* Private constructor - use JSBI.BigInt() to create instances
*/
private constructor();
/**
* Internal sign bit - true for negative numbers
*/
private sign: boolean;
/**
* Converts JSBI to string representation
* @param radix - Base for conversion (2-36), defaults to 10
* @returns String representation
*/
toString(radix?: number): string;
/**
* Returns debug string showing internal structure
* @returns Debug representation
*/
toDebugString(): string;
/**
* Intentionally throws to prevent accidental coercion
* @throws Error directing to use toNumber()
*/
valueOf(): void;
}JSBI follows native BigInt error handling patterns:
BigInt()valueOf()Creating from different types:
const fromNumber = JSBI.BigInt(42);
const fromString = JSBI.BigInt("12345678901234567890");
const fromHex = JSBI.BigInt("0x1a2b3c4d5e6f");
const fromBinary = JSBI.BigInt("0b1010101010");
const fromBoolean = JSBI.BigInt(true); // 1nString conversion for output:
const big = JSBI.BigInt("123456789");
console.log(big.toString()); // "123456789"
console.log(big.toString(16)); // "75bcd15" (hexadecimal)
console.log(String(big)); // "123456789"
// Explicit conversion needed for console.log
console.log(big); // Shows internal object structureChaining operations:
const result = JSBI.add(
JSBI.multiply(JSBI.BigInt("100"), JSBI.BigInt("200")),
JSBI.BigInt("300")
); // (100 * 200) + 300 = 20300Working with native transpilation:
// JSBI code that can be mechanically converted to native BigInt:
const a = JSBI.BigInt(42);
const b = JSBI.add(a, JSBI.BigInt(8));
// Transpiles to:
// const a = BigInt(42);
// const b = a + BigInt(8);