Number.isInteger()

JavaScript has no integer type, so this asks about the value rather than the type: is this double a whole number? Its companion isSafeInteger adds the requirement that the value be exactly representable.

Number static methodES2015Live demo
Common call
Number.isInteger(x)
Returns
boolean
Replaces
x % 1 === 0, which coerces strings
Watch out
a numeric string is FALSE — convert first
Number.isInteger(valuevalue — Any value. Non-numbers return false without conversion. Infinity and NaN are false; 5.0 is true, because it is indistinguishable from 5.type: any · required)
→ boolean

Demo

Live evaluation
Try:
Inputs
vanyany value
Output
Number.isInteger(5)
true

Whole numbers are true, fractions false, and non-numeric text false. What the demo cannot easily show is the no-coercion rule that matters most: Number.isInteger('5') — the STRING five — is false, because a string is not a number no matter what it looks like. The auto input here converts numeric-looking text to a real number before the call, which is exactly the conversion your own code has to do first. Also worth knowing: 5.0 is true, since JavaScript stores it identically to 5.

Parameters

NameTypeRequiredDescription
valueanyyesAny value. Non-numbers return false without conversion. Infinity and NaN are false; 5.0 is true, because it is indistinguishable from 5.

Return value

boolean — True if the value is a number with no fractional part. No coercion — a numeric STRING is false, because it is not a number at all.

Common patterns

Validate a parsed value
Convert first, then test.
const n = Number(input);
if (!Number.isInteger(n)) reject();
Guard an array index
Whole, non-negative and in range.
const ok = Number.isInteger(i) && i >= 0 && i < arr.length;
Check precision as well
isSafeInteger for ids and counters.
if (!Number.isSafeInteger(id)) throw new Error("id too large");

Examples

1. A whole number
Number.isInteger(5)
Returns
true
2. 5.0 is the same
Number.isInteger(5.0)
Returns
true
3. A fraction
Number.isInteger(5.5)
Returns
false
4. A string is false
Number.isInteger('5')
Returns
false
5. Past the safe limit
Number.isSafeInteger(2 ** 53)
Returns
false
6. Just inside it
Number.isSafeInteger(2 ** 53 - 1)
Returns
true

Pitfalls

1. A numeric string is false
Deliberate — the method tests the value, and a string is not a number. Form input arrives as text, so validation must convert first. Forgetting gives a validator that rejects every legitimate entry.
Rejects valid input
Number.isInteger('5')
false
Convert first
Number.isInteger(Number('5'))
true
2. 5.0 is an integer, and 5 is a float
There is only one numeric type. A value that arrived as 5.0 from JSON is stored exactly as 5, so this returns true and there is no way to recover the distinction. Code that needs to know whether the source text had a decimal point must inspect the text.
Indistinguishable
Number.isInteger(5.0)
true
Check the source
'5.0'.includes('.')
true
3. Integer does not mean safe
Past 2⁵³ values are still whole numbers, so isInteger stays true while arithmetic silently loses precision. For ids, counters and timestamps the stricter isSafeInteger is the right test.
Still true
Number.isInteger(2 ** 53 + 2)
true
Stricter
Number.isSafeInteger(2 ** 53 + 2)
false
4. The old modulo trick coerces
x % 1 === 0 was the pre-2015 idiom and it converts its operand, so it answers true for the string "5", for an empty array, and for null. This method does not convert anything.
Coerces
'5' % 1 === 0
true
Does not
Number.isInteger('5')
false

When to use

Use it
  • Validating that a converted value is whole
  • Guarding array indices and counts
  • Rejecting fractional input where only whole units make sense
  • With isSafeInteger, checking ids have not lost precision
Reach for something else
  • The value is a string → convert with Number first
  • You need the whole part → Math.trunc or Math.floor
  • Large exact integers → BigInt
  • Checking for any number → Number.isFinite

Notes

Complexity
O(1)
Return
A boolean; nothing is allocated or coerced
CPython impl
V8: Builtins-number-isinteger
Memory
No allocation
Thread-safe
Single-threaded

FAQ

Because the argument is a string, and the method performs no conversion — that is the whole design. The global-style predicates that DO convert, such as isNaN, are exactly the ones ES2015 added replacements for.

Number.isInteger(Number('5'));   // true

History

ES2015
Number.isInteger and Number.isSafeInteger added with the non-coercing predicates.