typeof
The operator that returns a string describing a value’s type. Fast and safe — it never throws, even on undeclared variables.
When to use it
- Type checking — determine if a value is a string, number, function, etc.
- Guard clauses — branch logic based on input type
- Feature detection — check if a global exists without a ReferenceError
- Defensive code — handle unexpected types at system boundaries
Anatomy
typeof 'hello' // 'string'
typeof 42 // 'number'
typeof true // 'boolean'
typeof undefined // 'undefined'
typeof Symbol() // 'symbol'
typeof 10n // 'bigint'
typeof function(){} // 'function'
// the famous quirks
typeof null // 'object' — a bug since JS v1, never fixed
typeof [] // 'object' — arrays are objects
typeof {} // 'object' — plain objects
typeof new Date() // 'object' — everything constructed with newAt a glance
| Value | typeof result |
|---|---|
'hello' | 'string' |
42 / NaN / Infinity | 'number' |
true / false | 'boolean' |
undefined | 'undefined' |
null | 'object' (known bug) |
Symbol() | 'symbol' |
10n | 'bigint' |
function() {} | 'function' |
{} / [] / new Date() | 'object' |
1. Simple — basic type check
function greet(name) {
if (typeof name !== 'string') {
throw new TypeError(`Expected string, got ${typeof name}`)
}
return `Hello, ${name}`
}
greet('Alice') // 'Hello, Alice'
greet(42) // TypeError: Expected string, got number2. Intermediate — safe global check
// checking an undeclared variable normally throws ReferenceError
// console.log(myGlobal) // ReferenceError: myGlobal is not defined
// typeof is the one operator that doesn't throw on undeclared variables
if (typeof window !== 'undefined') {
// we're in a browser
}
if (typeof process !== 'undefined') {
// we're in Node.js
}3. Advanced — runtime type narrowing
function serialize(value) {
switch (typeof value) {
case 'string':
return `"${value}"`
case 'number':
case 'boolean':
return String(value)
case 'object':
if (value === null) return 'null' // handle the null quirk
if (Array.isArray(value)) return `[${value.map(serialize).join(',')}]`
return `{${Object.entries(value).map(([k, v]) => `"${k}":${serialize(v)}`).join(',')}}`
case 'undefined':
return 'undefined'
default:
return String(value)
}
}
serialize({ name: 'Alice', scores: [10, 20], active: true })
// '{"name":"Alice","scores":[10,20],"active":true}'Gotchas
typeof null is ‘object’
typeof null // 'object' — not 'null'
// always check for null explicitly
function isObject(val) {
return val !== null && typeof val === 'object'
}
isObject({}) // true
isObject(null) // false
isObject([]) // true — arrays are objects tootypeof NaN is ‘number’
typeof NaN // 'number' — NaN is technically a number value
// use Number.isNaN() for a reliable check
Number.isNaN(NaN) // true
Number.isNaN('hello') // false — doesn't coerce like the global isNaNBetter alternatives for objects
typeof [] // 'object' — not helpful
Array.isArray([]) // true — reliable array check
typeof new Date() // 'object'
date instanceof Date // true — reliable for built-in types
// for plain objects
typeof {} // 'object' — same as null, arrays, dates...Related
Last updated on