A Number is a double with a 53-bit significand, so integers are exact only up to a point. Safe integers run from -(2 ** 53 - 1) to 2 ** 53 - 1 (Number.MIN_SAFE_INTEGER to Number.MAX_SAFE_INTEGER). Per MDN, a safe integer is exactly representable and no other integer rounds to it. 2 ** 53 is representable, but 2 ** 53 + 1 rounds to it, so the two are indistinguishable. Number.isSafeInteger(x) checks for an integer in this range.
Use BigInt when you need exact integers beyond that: 64-bit database IDs, nanosecond timestamps, big factorials.
How BigInt works:
- Create with a literal (
123n) orBigInt(value).typeof 1nis"bigint". - Arbitrary precision:
2n ** 64nis exact. - Arithmetic works with
+ - * / % **. Division truncates toward zero:5n / 2nis2n. - No mixing with
Numberin arithmetic.1n + 1throws aTypeError; convert explicitly withBigInt(x)orNumber(b). Comparisons do mix:1n < 1.5and1n == 1aretrue,1n === 1isfalse. BigInt(1.5)throwsRangeError; only integers convert.- No
Math.*methods, no unary+, no>>>. JSON.stringifythrows on a BigInt; convert to string yourself.BigInt.asIntN(bits, n)/asUintNwrap a value to a signed / unsigned width, like a fixed-size integer type.
Convert with care: Number(bigint) above the safe range loses precision, and BigInt(unsafeNumber) only preserves what the Number already lost.