Skip to Content
Built Instypeof

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 new

At a glance

Valuetypeof 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 number

2. 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 too

typeof 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 isNaN

Better 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...

  • Errortypeof err is 'object', use instanceof Error instead
  • Arraytypeof [] is 'object', use Array.isArray()
Last updated on