How Lodash isSafeInteger Handles BigInt Values
Lodash's _.isSafeInteger method evaluates whether a
provided value is an integer within JavaScript's safe floating-point
limit, and it always returns false when passed a
BigInt, regardless of how large that BigInt
is. This article breaks down why Lodash treats massive
BigInt instances this way, the internal type checks that
trigger this result, and how to handle arbitrary-precision integers
correctly in modern JavaScript applications.
The Definition of a "Safe Integer"
In JavaScript, the term "safe integer" has a precise technical
definition derived from the IEEE-754 double-precision floating-point
specification. A safe integer is any whole number between
-(2^53 - 1) (Number.MIN_SAFE_INTEGER) and
2^53 - 1 (Number.MAX_SAFE_INTEGER). Within
this boundary, every integer has an exact representation and can be
compared or incremented without precision loss.
Values outside this range cannot be safely represented using standard
JavaScript Number primitives. When ES2020 introduced
BigInt to solve the precision limit for arbitrarily large
numbers, it introduced a distinct primitive type (bigint)
separate from the standard number type.
How Lodash Evaluates BigInt Primitives
When passed a massive BigInt (such as
10n ** 100n or 9007199254740993n),
_.isSafeInteger immediately returns false.
Under the hood, Lodash's implementation relies on two core criteria:
- Type Checking: The input must be a number primitive
or a
Numberobject. Lodash's internal predicates verifytypeof value == 'number'or verify the object tag viaObject.prototype.toString.call(value) === '[object Number]'. Since a massiveBigInthas the primitive typebigint, it fails this preliminary guard clause immediately. - Safe Integer Verification: Lodash delegates to
Number.isSafeInteger(value)or checks ifvalue >= -9007199254740991 && value <= 9007199254740991. Because the value fails the type check, the numeric boundary logic is never reached.
Importantly, passing a BigInt to
_.isSafeInteger does not throw a TypeError.
While native arithmetic operations that mix BigInt and
Number types throw an error, Lodash's non-strict type
assertion mechanisms simply fail gracefully, returning
false.
Handling and Validating Massive BigInts
Because _.isSafeInteger is strictly meant for standard
IEEE-754 numbers, relying on it to validate BigInt data
will lead to false negatives.
If an application requires checking whether a value is a valid
BigInt, native JavaScript provides direct alternatives:
- Type Verification: Use
typeof value === 'bigint'to confirm if a representation is an arbitrary-precision integer. - Safe Range Boundaries: If you need to check if a
BigIntcan be safely cast down to a standardNumber, compare it directly againstBigInt(Number.MAX_SAFE_INTEGER)andBigInt(Number.MIN_SAFE_INTEGER).
function isBigIntSafeAsNumber(val) {
return typeof val === 'bigint' &&
val >= BigInt(Number.MIN_SAFE_INTEGER) &&
val <= BigInt(Number.MAX_SAFE_INTEGER);
}In summary, _.isSafeInteger rejects all
BigInt values by design. Massive BigInts represent values
that exceed standard safe integer capabilities, making
false both the expected and technically accurate response
within Lodash.