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:

  1. Type Checking: The input must be a number primitive or a Number object. Lodash's internal predicates verify typeof value == 'number' or verify the object tag via Object.prototype.toString.call(value) === '[object Number]'. Since a massive BigInt has the primitive type bigint, it fails this preliminary guard clause immediately.
  2. Safe Integer Verification: Lodash delegates to Number.isSafeInteger(value) or checks if value >= -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:

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.