Desk Clarity

A field guide to everyday digital problems.

Developer tools / Practical guide

NaN Is Not Equal to Itself: Separate Invalid Numbers from Membership

Use Number.isNaN to detect the NaN numeric value without coercion.

By ON Lab2 min readSources checked November 10, 2026 (KST)

Use Number.isNaN to detect the NaN numeric value without coercion. Equality comparisons and array membership do not all use the same rule, so choose a check that matches the input contract.

Reproduce the behavior safely

Run this self-contained fixture in an empty temporary directory, separate from your project. Shell examples create only named fixture files there. JavaScript examples use local values and send no network requests.

const assert = require('node:assert/strict');
const invalid = Number('not-a-count');
assert.equal(invalid === NaN, false);
assert.equal(Number.isNaN(invalid), true);
assert.equal(Number.isNaN('not-a-count'), false);
assert.equal(isNaN('not-a-count'), true);
assert.equal([invalid].indexOf(NaN), -1);
assert.equal([invalid].includes(NaN), true);
assert.equal(Number.isFinite(Infinity), false);
console.log('NaN detection, coercion and membership are distinct');

Observed local output

NaN detection, coercion and membership are distinct

Why the result changes

A comparison against NaN is false even when the value is NaN. Number.isNaN checks the existing value, while the global isNaN first converts its input. The array checks show another distinction: includes can find NaN, whereas indexOf does not find it through strict equality. None of those results establishes whether a user supplied an acceptable count.

Choose and verify the correction

Choose a parsing policy first. If numeric strings are permitted, validate their syntax and convert deliberately; if only numbers are accepted, check the type before arithmetic. Then reject nonfinite values when the domain requires finite numbers. For counts, also check integer and range constraints. Preserve the original input for a bounded diagnostic rather than allowing an invalid conversion to propagate into totals or JSON.

Limits and next checks

The example is an executed Node fixture, not a form-validation library. Number.isNaN alone accepts neither nor rejects Infinity as a valid domain value; that is a separate condition. Empty strings and whitespace can convert to zero under Number, so successful conversion is not proof of meaningful input. Object membership uses reference identity and is covered in a separate guide.

Related: Includes Returns False for a Similar Object: Match the Intended Identity.

Isolated fixture executed on macOS on November 10, 2026 (KST), with v26.5.0. The observed output verifies this example, not every application or runtime.

Sources & further reading