JavaScript has 7 primitive types and 1 object type. The typeof operator, instanceof, and Object.prototype.toString each give you different information — and each has quirks. This article covers the type system and every type-checking tool, including the traps interviewers specifically test.
1. The 8 Types
Primitives (7): string number bigint boolean undefined symbol null
Object (1): everything else — arrays, functions, dates, maps, sets, classes...
Primitives are immutable and compared by value. Objects are compared by reference.
Loading editor...
2. typeof — The Primary Tool
Loading editor...
The Two Classic typeof Traps
Trap 1: typeof null === 'object' — This is a bug from JavaScript's first implementation that can't be fixed without breaking the web. Always check value === null separately.
Trap 2: typeof [] === 'object' — Arrays are objects, so typeof can't distinguish them. Use Array.isArray().
Loading editor...
3. instanceof — Prototype Chain Check
Checks if an object's prototype chain contains a specific constructor's .prototype.
Loading editor...
The Cross-Realm Problem
instanceof fails when objects come from a different JavaScript realm (iframe, VM context). Each realm has its own Array, Date, etc.
Loading editor...
This is why libraries prefer Object.prototype.toString.call() for type checking.
4. Object.prototype.toString.call(value) — Most Reliable
Returns [object InternalType] where InternalType is the engine's internal class.
Loading editor...
This works across realms — it always reflects the engine's internal class.
5. Array.isArray(value) — Array-Specific Check
Loading editor...
This is the only reliable way to detect arrays. It works across realms (unlike instanceof Array).
6. Checking for Specific Primitive Types
Loading editor...
7. NaN, Infinity, and -0
NaN Detection
Loading editor...
Infinity
Loading editor...
-0
Loading editor...
8. Object.is(a, b) — Most Precise Equality
Loading editor...
Object.is is SameValue equality — the strictest comparison. Use it when you need exact equivalence.
Quick Reference
| Check | Tool | Watch Out |
|---|---|---|
| Is it null? | v === null | typeof null === 'object' |
| Is it array? | Array.isArray(v) | typeof [] === 'object' |
| Is it NaN? | Number.isNaN(v) | NOT isNaN(v) — it coerces |
| Is it finite? | Number.isFinite(v) | NOT isFinite(v) — it coerces |
| Is it integer? | Number.isInteger(v) | |
| General type | typeof v | Handles most primitives + functions |
| Cross-realm type | Object.prototype.toString.call(v) | Most reliable |
| Prototype check | v instanceof Constructor | Doesn't work across realms |
| Strictest equality | Object.is(a, b) | NaN and +0/-0 correct |
Interview Tips
- Always check
nullbeforetypeof—typeof null === 'object'will trip you. - Use
Array.isArray— nevertypeoffor arrays. - Use
Number.isNaN— not the globalisNaN. - Use
Object.prototype.toString.callfor generic type tags — it's the nuclear option that always works.