d3DetectabilityOperational debt — how invisible misuse is to your safety net
Closest to 'default linter catches the common case' (d3). The detection_hints list ESLint and TypeScript, and the code_pattern explicitly notes 'typeof x === 'object' without null check' — ESLint rules (e.g. no-eq-null, eqeqeq, or typescript-eslint) can flag the common typeof null and array misuse patterns in routine linting.
e1EffortRemediation debt — work required to fix once spotted
Closest to 'one-line patch or single-call swap' (e1). The quick_fix is a direct one-line substitution: replace typeof x === 'object' with typeof x === 'object' && x !== null, use === null for null checks, and use Array.isArray() for arrays. Each fix is a local, mechanical replacement requiring no structural change.
b3BurdenStructural debt — long-term weight of choosing wrong
Closest to 'localised tax' (b3). The mistake applies to individual type-check call sites across web and CLI contexts, but incorrect typeof usage is self-contained at each check point. It doesn't propagate architectural debt or impose a system-wide design constraint; it's a recurring but localised correction tax.
t7TrapCognitive debt — how counter-intuitive correct behaviour is
Closest to 'serious trap' (t7). The misconception field states explicitly that typeof is assumed sufficient for all type checks, but typeof null === 'object' is a well-known language bug that contradicts what the name implies, and typeof [] === 'object' further contradicts intuition from other languages or even from JavaScript's own naming. A competent developer new to JS would reasonably expect typeof null to return 'null' — the actual behaviour directly contradicts the mental model, placing it at t7.
About DEBT scoring →
scored by claude-sonnet-4-6 · 2026-05-10 · reviewed by human
Also Known As
typeof null bugnull type checktypeof object quirk
TL;DR
typeof returns a string describing the type — but typeof null === 'object' is a famous historical bug that cannot be fixed without breaking the web, requiring explicit null checks alongside typeof.
Explanation
The typeof operator returns one of: 'undefined', 'boolean', 'number', 'bigint', 'string', 'symbol', 'function', or 'object'. The bug: typeof null === 'object', which is wrong — null is not an object. This was a bug in the original JavaScript that became load-bearing and cannot be fixed. To check for null specifically, use value === null. To check for an object that is not null, use typeof value === 'object' && value !== null. TypeScript's type narrowing handles this automatically. PHP's gettype() behaves more sensibly: gettype(null) returns NULL.
Watch Out
⚠ Checking typeof value === 'object' to detect objects will match null, arrays, and functions (in older engines), so you must always pair it with value !== null and often typeof value !== 'function' — a single typeof check is never sufficient for object detection.
Common Misconception
✗ typeof is sufficient for all type checks — typeof null returns 'object' (a known bug), arrays also return 'object', and you need instanceof or Array.isArray() for those cases.
Why It Matters
Incorrect typeof checks cause 'cannot read property of null' errors — understanding the null quirk and how to properly check types prevents an entire class of runtime bugs.
Common Mistakes
Using typeof x === 'object' without checking x !== null
Not using Array.isArray() for array checks — typeof [] === 'object'
Using typeof for null checks instead of === null
Code Examples
✗ Vulnerable
// Unreliable type checks:
if (x == null) { } // Catches both null and undefined
typeof null === 'object' // Bug — null is not an object
NaN === NaN // false — can't use ===
✓ Fixed
// Reliable checks:
if (x === null) { } // Only null
if (x === undefined) { } // Only undefined
if (x == null) { } // null OR undefined (intentional)
Number.isNaN(x) // Correct NaN check
Array.isArray(x) // Correct array check
🧱FUNDAMENTALS— new to this? Start with the ground floor.
JavaScriptjavascriptThe programming language of the browser — it reads and modifies the page (the DOM), reacts to user events, and fetches data without reloading.
JavaScript is the only language browsers execute, so every interactive behaviour on the web goes through it. Its two defining traits — single-threaded event loop and loose typing (== coercion) — explain the majority of both its bugs and its design patterns.
💡 Default to const, use === always, and reach for let only when a value genuinely reassigns.
For null checks always use === null; for arrays use Array.isArray(); for non-null object use typeof x === 'object' && x !== null — or switch to TypeScript