undefined vs null — Subtle Differences
debt(d5/e3/b3/t7)
Closest to 'specialist tool catches it' (d5). The detection_hints list ESLint and TypeScript as tools. ESLint with eqeqeq rule catches loose == comparisons, and TypeScript with strict null checks catches type mismatches, but neither is a default out-of-the-box configuration — you need to opt into strict modes or specific rules. The JSON serialisation difference is silent at runtime unless tested explicitly.
Closest to 'simple parameterised fix' (e3). The quick_fix is concrete: replace explicit undefined assignments with null, swap == with ===, adopt ?? for nullish coalescing, and enable TypeScript strict null checks. This is a small pattern-replacement effort within a component, not a one-liner but not a multi-file architectural change.
Closest to 'localised tax' (b3). The applies_to covers web and cli broadly, but the confusion is localised to specific comparison and serialisation sites. It imposes a persistent awareness tax on developers writing comparisons or API contracts, but doesn't reshape the whole codebase architecture.
Closest to 'serious trap' (t7). The misconception field explicitly states that developers treat null and undefined as interchangeable — a belief reinforced by the fact that null == undefined is true under loose equality. The JSON.stringify behaviour difference (drops undefined, preserves null) contradicts what most developers expect, especially given how similar the two values appear semantically.
TL;DR
Explanation
undefined: default value of unassigned variables, missing object properties, missing function parameters, void function return. null: explicit absence, intentional empty value. Key differences: typeof undefined === 'undefined', typeof null === 'object' (JS bug from 1995, can't fix). null == undefined (true), null === undefined (false). JSON.stringify converts undefined to nothing, null to 'null'. Optional chaining: obj?.prop returns undefined for missing, not null. Best practice: use null for intentional absence, never assign undefined explicitly.
Common Misconception
Why It Matters
Common Mistakes
- Assigning undefined explicitly — use null for intentional absence.
- Using == instead of === which treats null and undefined as equal.
- Forgetting that JSON.stringify drops undefined values but preserves null.
Code Examples
// Both are falsy but behave differently:
const a = null;
const b = undefined;
console.log(a == b); // true
console.log(a === b); // false
console.log(JSON.stringify({a, b})); // {"a":null} (b dropped!)
// Explicit null for intentional absence:
const user = fetchUser() ?? null; // null if not found
// Strict null checks:
if (value === null) { /* intentionally empty */ }
if (value === undefined) { /* not yet set */ }
if (value == null) { /* either null or undefined */ }
// TypeScript helps:
function getUser(id: string): User | null { }