Number.isInteger()
Number.isInteger(value) The Number.isInteger() method determines whether the passed value is an integer. This is useful for validating user input, checking API responses, or ensuring calculations produce whole numbers. In JavaScript, integers are numbers without a fractional component, and this method provides a reliable way to test for them.
Syntax
Number.isInteger(value)
Parameters
| Parameter | Type | Description |
|---|---|---|
value | any | The value to check |
Return Value
Returns true if the value is an integer (a whole number without any fractional component). Returns false for non-integers, non-number types, and special values like Infinity, -Infinity, and NaN.
Examples
Basic usage
Number.isInteger(42); // true
Number.isInteger(0); // true
Number.isInteger(-10); // true
Number.isInteger(1000); // true
Floating point numbers
Floating point numbers return false because they have a fractional component. The method checks the internal representation, so 3.14159 and 0.1 are both rejected, even though 0.1 looks simple. This is the expected behavior for any value that cannot be stored as a whole number in IEEE 754.
Number.isInteger(3.14159); // false
Number.isInteger(1.5); // false
Number.isInteger(0.1); // false
Number.isInteger(-2.5); // false
Edge cases: integer-like floats
JavaScript does not distinguish between 1 and 1.0 at the language level — the engine normalizes both to the same internal representation before the check runs. This means isInteger(1.0) returns true because the value is stored identically to 1. Keep this in mind when validating values that arrive as floating-point literals.
// These are technically floats but are considered integers by isInteger
Number.isInteger(1.0); // true (1.0 equals 1)
Number.isInteger(42.0); // true
Number.isInteger(-5.0); // true
Special values
Special numeric values return false. Infinity is not a finite integer, and NaN is not a number at all, so both are rejected. This is important when validating values that might come from calculations like 1/0 or parseInt("abc"), which produce Infinity and NaN respectively.
Number.isInteger(Infinity); // false
Number.isInteger(-Infinity); // false
Number.isInteger(NaN); // false
Non-number types
Non-number types always return false. Unlike the older global isFinite(), which coerces strings, Number.isInteger() does not convert its argument. A string like '42' stays a string and fails the check, which prevents accidental acceptance of user input that has not yet been parsed.
Number.isInteger('42'); // false (string)
Number.isInteger('hello'); // false
Number.isInteger(undefined); // false
Number.isInteger(null); // false
Number.isInteger(true); // false (boolean)
Number.isInteger(false); // false
Number.isInteger({}); // false (object)
Number.isInteger([]); // false (array)
Common patterns
Form validation
Validating that user input is a whole number:
function validateAge(input) {
if (!Number.isInteger(input)) {
return 'Age must be a whole number';
}
if (input < 0 || input > 150) {
return 'Age must be between 0 and 150';
}
return 'Valid';
}
validateAge(25); // 'Valid'
validateAge(25.5); // 'Age must be a whole number'
validateAge(-5); // 'Age must be between 0 and 150'
Array index validation
Ensuring an index is a valid integer before using it to access an array prevents undefined lookups and hard-to-debug errors. The index must be a whole number and must fall within the array bounds. This guard is useful in utility functions that accept an index from callers you don’t control.
function getItem(arr, index) {
if (!Number.isInteger(index)) {
throw new Error('Index must be an integer');
}
if (index < 0 || index >= arr.length) {
throw new Error('Index out of bounds');
}
return arr[index];
}
const items = ['a', 'b', 'c'];
getItem(items, 1); // 'b'
getItem(items, 1.5); // Error: Index must be an integer
Loop counter validation
When a function creates an array based on a caller-supplied length, checking that the length is a positive integer avoids silent errors. A fractional length like 3.5 would otherwise round or throw in confusing ways. The guard below rejects non-integer and non-positive values before new Array(length) ever runs.
function createArray(length) {
if (!Number.isInteger(length) || length <= 0) {
throw new Error('Length must be a positive integer');
}
return new Array(length).fill(0);
}
createArray(5); // [0, 0, 0, 0, 0]
createArray(3.5); // Error: Length must be a positive integer
Type coercion comparison
Unlike some other methods, Number.isInteger() does not coerce its argument. The first two lines show the difference: wrapping '42' in Number() converts it to the numeric 42 before the check, so it passes. Without that explicit conversion, the string is rejected. This contrast is worth remembering when reading values from form inputs or query strings.
// Comparison with the global approach (Number() conversion)
Number.isInteger(Number('42')); // true (after coercion to 42)
Number.isInteger('42'); // false (string, not coerced)
Number.isInteger(Number('3.14')); // false (after coercion to 3.14)
Number.isInteger('3.14'); // false (string)
Filtering arrays
Number.isInteger works directly as a filter callback because it takes a single argument and returns a boolean. The first filter call collects the whole numbers, and the negated version collects everything else. This pattern is concise but works only when all array elements are already numbers.
const mixed = [1, 2.5, 3, 4.5, 5, 6, 7.5];
const integers = mixed.filter(Number.isInteger);
// [1, 3, 5, 6]
const floats = mixed.filter(x => !Number.isInteger(x));
// [2.5, 4.5, 7.5]
Combined validation
A single function can check several numeric properties in sequence: finiteness, integrality, and range. Order matters here — checking isInteger first would accept Infinity if you allowed it, so the finite check comes first. The returned object makes it clear whether the value passed and, if not, which constraint it violated.
function processQuantity(value) {
if (typeof value !== 'number' || !Number.isFinite(value)) {
return { error: 'Must be a finite number' };
}
if (!Number.isInteger(value)) {
return { error: 'Must be an integer' };
}
if (value < 0) {
return { error: 'Must be non-negative' };
}
return { success: true, value };
}
processQuantity(10); // { success: true, value: 10 }
processQuantity(10.5); // { error: 'Must be an integer' }
processQuantity(Infinity); // { error: 'Must be a finite number' }
Why this check is useful
Number.isInteger() is a good guard when the next step assumes a whole number. That includes array indexes, page numbers, counters, pagination offsets, and quantity fields that should not accept fractional values. Using the check early gives you a clear place to reject invalid input before it reaches the rest of your logic.
Unlike older patterns such as value % 1 === 0, the built-in method reads like a direct question and does not coerce the input. That makes it easier to explain to teammates and safer when values may arrive as strings, booleans, or other unexpected types from a form or API payload.
Integer values vs numeric strings
A common source of confusion is the difference between the number 42 and the string "42". They may look the same on screen, but they behave differently in code. Number.isInteger("42") returns false because the argument is not a number at all. If you want to accept numeric text, convert it first, then validate the result.
That pattern is especially useful for parsing form fields. First turn the value into a number, then make sure it is finite and integer-valued. Doing those steps in order keeps your validation predictable and prevents accidental acceptance of values like "", null, or "3.5".
See also
- Number.isFinite() — check if value is a finite number
- Number.isNaN() — check if value is NaN
- JSON.parse() — parse a JSON string