Online Compiler logoOnline Compiler

JavaScript Tutorial

The `typeof` Operator

`typeof` returns a string describing the type of a value. It’s useful for quick checks but has known edge cases to watch out for. The typeof operator is one of JavaScript's oldest features and provides runtime type information, though it has some historical quirks that developers need to understand.

Why this matters

Use `typeof` for robust runtime checks (e.g., guard clauses) while knowing its limitations. It's essential for defensive programming and handling dynamic data, but should be used carefully due to its edge cases.

Return Values

`typeof` can return 'string', 'number', 'boolean', 'undefined', 'object', 'function', or 'symbol'. Each return value corresponds to a specific JavaScript type.

'bigint' is returned for BigInt values (ES2020+). 'symbol' for Symbol values. 'function' for callable objects.

'object' for objects, arrays, null, and other non-primitive values. This is where most confusion arises.

'undefined' for declared but unassigned variables, missing properties, and void returns.

Common Pitfalls

`typeof null` returns 'object' due to legacy reasons. This is a well-known bug in JavaScript that has been preserved for backward compatibility.

Arrays and objects both return 'object'. Cannot distinguish between {} and [] using typeof alone.

Date objects, RegExp objects, and other built-in objects all return 'object'.

Primitive wrapper objects (new String(), new Number()) return 'object', not their primitive counterparts.

Typeof with Primitives

Numbers: typeof 42 === 'number', typeof NaN === 'number', typeof Infinity === 'number'. All numeric values return 'number'.

Strings: typeof 'hello' === 'string', typeof `template` === 'string'. All string literals and expressions return 'string'.

Booleans: typeof true === 'boolean', typeof false === 'boolean'. Boolean literals return 'boolean'.

Undefined: typeof undefined === 'undefined'. Also returned for undeclared variables in non-strict mode.

Symbols: typeof Symbol() === 'symbol'. Unique identifiers return 'symbol'.

BigInts: typeof 42n === 'bigint'. Large integers return 'bigint'.

Typeof with Objects

Plain objects: typeof {} === 'object'. All objects return 'object'.

Arrays: typeof [] === 'object'. Arrays are objects in JavaScript.

Functions: typeof function(){} === 'function'. Functions are callable objects.

Null: typeof null === 'object'. Historical bug, don't rely on this.

Dates: typeof new Date() === 'object'. Date instances are objects.

Regular expressions: typeof /regex/ === 'object'. RegExp objects return 'object'.

Practical Usage Patterns

Checking for undefined: Use typeof variable === 'undefined' instead of direct comparison to avoid ReferenceError.

Function detection: typeof func === 'function' to check if a value is callable.

Primitive checks: Combine typeof with value checks for robust primitive detection.

Guard clauses: Use typeof in defensive programming to handle dynamic data safely.

Feature detection: Check if browser APIs exist using typeof before calling them.

Library type checking: Build utility functions that combine typeof with other checks.

Better Type Checking Alternatives

Array.isArray(): Specifically checks for arrays, more reliable than typeof.

Number.isNaN(): Checks for NaN values, more reliable than isNaN().

Object.prototype.toString(): Returns '[object Type]' for precise type detection.

instanceof: Checks prototype chain, useful for custom object types.

constructor property: Can be spoofed, less reliable than other methods.

Custom type guards: Functions that perform comprehensive type checking.

Edge Cases and Gotchas

Undeclared variables: In non-strict mode, typeof undeclaredVar === 'undefined'. In strict mode, ReferenceError.

Document.all: Ancient IE object where typeof document.all === 'undefined' despite existing.

Host objects: Browser DOM objects may have unpredictable typeof behavior.

Primitive wrappers: new String('hi') has typeof 'object', not 'string'.

Callable objects: Some objects are callable but typeof returns 'object', not 'function'.

Proxy objects: typeof proxy returns the typeof of the target object.

Performance and Best Practices

Typeof is fast: One of the fastest operations in JavaScript, suitable for hot code paths.

Use for primitives: Excellent for checking primitive types and undefined.

Combine with other checks: Use Array.isArray(), instanceof for complex types.

Avoid for null checks: Use === null instead of typeof === 'object'.

TypeScript alternative: Use static typing to catch type errors at compile time.

Runtime validation: Combine typeof with schema validation libraries for robust checking.

Common Patterns

Safe property access: Check if object exists before accessing properties.

Function parameter validation: Use typeof to validate function arguments.

API response handling: Check types of data received from external sources.

Polyfill detection: Use typeof to check if modern features are available.

Module loading: Check if required modules are loaded using typeof.

Error handling: Validate error objects and thrown values.

Code Examples

Basic typeof Checks

console.log(typeof 42); // 'number'
console.log(typeof 'hi'); // 'string'
console.log(typeof null); // 'object'

Note the `null` edge case; use additional checks for precise type detection.

Primitive Type Detection

function isPrimitive(value) {
  const type = typeof value;
  return type === 'string' || 
         type === 'number' || 
         type === 'boolean' || 
         type === 'symbol' || 
         type === 'bigint' || 
         type === 'undefined';
}

console.log(isPrimitive(42)); // true
console.log(isPrimitive({})); // false
console.log(isPrimitive(null)); // false (typeof null === 'object')

Combine typeof with logic for comprehensive primitive checking.

Safe Undefined Checks

// Avoid: if (someVar === undefined) - throws if undeclared
// Better: use typeof
if (typeof someVar === 'undefined') {
  console.log('Variable is undefined');
}

// Works even for undeclared variables
console.log(typeof notDeclared); // 'undefined' (non-strict mode)

typeof is safe for checking undeclared variables.

Function Detection

function callIfFunction(func) {
  if (typeof func === 'function') {
    return func();
  }
  return null;
}

console.log(callIfFunction(() => 'called')); // 'called'
console.log(callIfFunction(42)); // null

Use typeof to check if a value is callable.

Array Detection (Wrong Way)

const arr = [1, 2, 3];
const obj = { length: 3 };

console.log(typeof arr); // 'object'
console.log(typeof obj); // 'object'

// Wrong way
function isArrayWrong(value) {
  return typeof value === 'object' && value !== null;
}

console.log(isArrayWrong(arr)); // true
console.log(isArrayWrong(obj)); // true (false positive)

typeof cannot distinguish arrays from objects.

Array Detection (Right Way)

const arr = [1, 2, 3];
const obj = { length: 3 };

console.log(Array.isArray(arr)); // true
console.log(Array.isArray(obj)); // false

// Comprehensive array check
function isArray(value) {
  return Array.isArray(value);
}

console.log(isArray(arr)); // true
console.log(isArray(obj)); // false

Use Array.isArray() for reliable array detection.

Complex Type Checking

function getType(value) {
  const type = typeof value;
  
  if (type === 'object') {
    if (value === null) return 'null';
    if (Array.isArray(value)) return 'array';
    if (value instanceof Date) return 'date';
    if (value instanceof RegExp) return 'regexp';
    return 'object';
  }
  
  return type;
}

console.log(getType(null)); // 'null'
console.log(getType([1, 2])); // 'array'
console.log(getType(new Date())); // 'date'
console.log(getType(/test/)); // 'regexp'

Combine typeof with instanceof and other checks for detailed type information.

Host Object Quirks

// In browsers
console.log(typeof window); // 'object'
console.log(typeof document); // 'object'
console.log(typeof console); // 'object'

// Some host objects may behave unexpectedly
console.log(typeof document.all); // 'undefined' in modern browsers

// Feature detection
if (typeof localStorage !== 'undefined') {
  // localStorage is available
}

Host objects (DOM, BOM) may have unusual typeof behavior.

Common Mistakes and Fixes

Relying solely on `typeof null`

Use `value === null` or Array.isArray for accurate checks.

Using typeof for array detection

Use Array.isArray() instead of typeof.

Assuming typeof works for host objects

Test behavior and use feature detection patterns.

Direct undefined comparison

Use typeof for safe undefined checks.

Ignoring primitive wrapper objects

Check for both primitives and wrapper objects.

Over-relying on typeof

Combine with other type checking methods for robustness.

Frequently Asked Questions

How to detect arrays?

Use `Array.isArray(value)`; `typeof` reports arrays as 'object'.

Why does typeof null return 'object'?

Historical bug from JavaScript's early days, preserved for backward compatibility.

Can typeof check for undeclared variables?

Yes, typeof undeclaredVar returns 'undefined' without throwing ReferenceError.

What's the difference between typeof and instanceof?

typeof checks primitive types, instanceof checks prototype chain for objects.

How to check if something is callable?

Use typeof value === 'function', but note some objects are callable too.

Is typeof slow?

No, typeof is one of the fastest operations in JavaScript.

Can I override typeof behavior?

No, typeof cannot be overridden or customized.

How does typeof work with symbols?

typeof Symbol() returns 'symbol', introduced in ES6.

Related JavaScript Topics