5 Shocking Reasons JavaScript typeof null Stays Broken Today
Table of Contents
Type three words into a JavaScript console and watch the language lie to your face: typeof null returns the string 'object'. Not 'null'. Not 'undefined'. Object. This is the most infamous of all JavaScript typeof null behaviors, and it has been wrong every single day for more than three decades.
The fix is one line. The reason it was never deployed is a story about a ten-day deadline, a borrowed trick from the C programming language, a rejected proposal, and a piece of the web so brittle that fixing one boolean check could break thousands of production sites. This is what JavaScript typeof null actually means, why it was never fixed, and how to safely check for null in your own code today.
What JavaScript typeof null Actually Returns
If you have never run this before, open your browser console and try it:
console.log(typeof null); // "object"
console.log(typeof undefined); // "undefined"
console.log(null === null); // true
console.log(null === undefined); // false
The first line is the whole story. JavaScript typeof null gives you the string "object" — the same answer you would get for an empty object literal or an array. But null is not an object.
Try to access a property on null and the language throws a TypeError immediately. Try null instanceof Object and you get false. The Null type is its own type in the official ECMAScript specification, completely distinct from the Object type. And yet typeof claims they are the same.
Every other primitive type reports itself correctly. Strings say “string”. Numbers say “number”. Booleans say “boolean”. Only null disagrees with the rest of the language about what kind of thing it is.
Reason 1: The 10-Day Deadline That Created JavaScript
Brendan Eich was given ten days in May of 1995 to design and ship a scripting language for Netscape Navigator 2. Not ten weeks. Not ten months. Ten days.
The pressure shaped every corner of the resulting language, and the JavaScript typeof null bug is one of the artifacts. To move that fast, Eich borrowed ideas from the languages around him. Function syntax came from C. First-class functions and closures came from Scheme.
Object prototypes came from Self. And the internal representation of values — the way the engine stored what type each variable was — came straight from a low-level trick used in C and early dynamic language runtimes.
That trick was bit-tagging. Every value would be packed into a small chunk of memory, and a few bits at the bottom of that chunk would act as a label telling the engine what kind of value it was looking at. It was clever, it was fast, and it was the exact moment the typeof null bug became inevitable.
Reason 2: Type Tags Made the JavaScript typeof null Bug Inevitable
The original SpiderMonkey engine packed type information into the lowest three bits of every value. The tag bits looked something like this:
// Conceptual type tag scheme (early SpiderMonkey)
// 000 -> object pointer
// 001 -> integer
// 010 -> double
// 100 -> string
// 110 -> boolean
// The engine reads a value's type by masking the lowest 3 bits
function readTypeTag(rawValue) {
return rawValue & 0b111;
}
To find out what type a value was, the engine read those three bits with a single mask operation. Blindingly fast. No table lookup, no type field, no extra memory. The typeof operator was implemented as essentially this mask, followed by a switch over the result.
And then there was null. In the C programming language that inspired this design, a null pointer is represented as all zeros in memory. JavaScript inherited that representation. A null value was just a 32-bit word of zero bits.
The engine would read its three lowest bits, see 000, and confidently return “object” — because 000 was the object tag. The bug was never a design decision. It was a side effect of two perfectly sensible choices that, combined, produced a wrong answer.
Reason 3: The Rejected Fix That Would Have Broken the Web
By the early 2000s the typeof null behavior was famous enough that fixing it became an obvious project. In 2009, during the drafting of what would eventually become ECMAScript 6, a TC39 committee member proposed a small patch: make typeof return the string “null” when given null. One line. Surgical. Correct.
The proposal went through the standard ECMAScript discussion process and was tested against real websites. The result was clear and uncomfortable: the change broke real production code. Not just a handful of legacy sites, but thousands of pages where developers had written something like this:
if (typeof config === "object") {
config.theme = config.theme ?? "dark";
}
That check was meant to identify real configuration objects. But because typeof null already returned “object”, null had been quietly slipping through for years. The downstream code worked because of follow-up null checks elsewhere, or because the application never actually fed null in.
Fixing typeof would have removed null from the bucket of values that satisfied that check. The downstream code would suddenly find itself dereferencing a real object that no longer existed in this code path. Across the web, this pattern was everywhere. Backwards compatibility won. The fix was abandoned.
Reason 4: Why JavaScript typeof null Will Never Be Fixed
The argument for fixing JavaScript typeof null comes down to correctness. The argument against it is the entire open web.
Once a piece of behavior, no matter how wrong, has been in every browser for more than a decade, removing it stops being a clean refactor and becomes a hostile act against every developer who shipped code that depends on it. The web has a much higher standard for backwards compatibility than most software ecosystems.
A new Python release can deprecate something today and remove it three minor versions later. A new operating system can drop an API and force everyone to migrate within a couple of years. JavaScript does not have that option. Browsers refuse to break the web.
So the typeof null bug became a kind of fossil. It is documented in the official ECMAScript specification as the explicit, expected behavior. Every JavaScript developer eventually learns about it. Linting tools warn against relying on it. And every browser still ships the wrong answer, because the cost of fixing it would land on millions of pages nobody wants to break.
Reason 5: The Safe Way to Check for null Today
The practical question is what to do about it in your own code. The answer is to never use the typeof operator to check for null. There are two clean patterns that always work.
The first pattern is a direct strict-equality check against null. It returns true only for the actual null value and nothing else:
function isNull(value) {
return value === null;
}
console.log(isNull(null)); // true
console.log(isNull(undefined)); // false
console.log(isNull(0)); // false
console.log(isNull("")); // false
The second pattern handles the common case where you want to treat null and undefined the same way — for example, when validating that a function argument was supplied. Loose equality against null catches both:
function isNullOrUndefined(value) {
return value == null;
}
console.log(isNullOrUndefined(null)); // true
console.log(isNullOrUndefined(undefined)); // true
console.log(isNullOrUndefined(0)); // false
If you actually want to check that a value is a real object — and not null pretending to be one — combine typeof with an explicit null check:
function isPlainObject(value) {
return typeof value === "object" && value !== null;
}
Once you internalize this pattern, the JavaScript typeof null bug stops mattering in practice. You write the explicit check, the language behaves correctly, and your future self stops getting bitten by null sneaking through where an object was expected. MDN’s typeof reference covers the full table of return values if you want to dig deeper into every edge case.
Watch the Full Breakdown
The complete origin story, the bit-tag diagrams, the rejected ECMAScript proposal, and the safe patterns are all walked through in the companion video below. It runs about three minutes.
For more deep dives into language internals, browser behavior, and the engineering choices that shaped the modern web, browse the rest of the Web Development section on this site.