JavaScript typeof Operator: Every Result and Its Quirks

By Marko Denic
Contents
  1. Every typeof result
  2. The syntax
  3. The quirks
  4. typeof null is "object"
  5. Arrays are "object"
  6. NaN is a "number"
  7. Classes are "function"
  8. Wrapper objects
  9. Practical uses
  10. Check if a variable exists
  11. Validate function arguments
  12. Get a precise type for anything
  13. typeof vs instanceof
  14. FAQ

The typeof operator returns a string that tells you the type of a value. It’s how you check, at runtime, whether something is a number, a string, a function, and so on:

typeof 42 returns "number", typeof "hi" returns "string".

It can only ever return one of eight strings, but a few of them are surprising. Here’s the full list, and how to handle the cases typeof gets “wrong”.

Every typeof result

Value typeof returns
undefined "undefined"
true, false "boolean"
42, 3.14, NaN, Infinity "number"
10n "bigint"
"text", '' "string"
Symbol('id') "symbol"
Functions, arrow functions, classes "function"
Objects, arrays, null, dates, regexes, maps "object"

The syntax

typeof is an operator, not a function, so parentheses are optional. They’re handy for expressions, because typeof binds tighter than most operators.

javascript
typeof 'hello';           // "string"
typeof('hello');          // "string" (same thing)

typeof 1 + 2;             // "number2"  → (typeof 1) + 2
typeof (1 + 2);           // "number"

The quirks

typeof null is "object"

A bug from the first version of JavaScript in 1995 that can never be fixed without breaking the web. Check for null directly instead.

javascript
typeof null;              // "object" (!)

value === null;           // the right check

// "is it a real object?"
value !== null && typeof value === 'object';

Arrays are "object"

Arrays are objects in JavaScript, so typeof can’t tell them apart. Use Array.isArray().

javascript
typeof [1, 2, 3];         // "object"
Array.isArray([1, 2, 3]); // true
Array.isArray({});        // false

NaN is a "number"

“Not a Number” is technically a numeric value: the result of failed math. Use Number.isNaN() to detect it, or Number.isFinite() to check for a usable number. You usually get NaN when you convert a string to a number and the string isn’t numeric.

javascript
typeof NaN;               // "number"
Number.isNaN(NaN);        // true
Number.isFinite('42');    // false: strings aren't numbers
Number.isFinite(42);      // true

Classes are "function"

A class is a special kind of function under the hood.

javascript
class User {}
typeof User;              // "function"
typeof new User();        // "object"

Wrapper objects

new String(), new Number() and new Boolean() create objects, not primitives. You almost never want them; call the functions without new to convert values.

javascript
typeof new String('hi');  // "object"
typeof String(42);        // "string" (conversion, no new)

Practical uses

Check if a variable exists

typeof is the only way to check an undeclared variable without a ReferenceError. That’s useful for feature detection and code that runs in both browsers and Node.js. (It does throw for let and const variables used before their declaration.)

javascript
if (typeof window !== 'undefined') {
  // running in a browser
}

if (typeof gtag === 'function') {
  gtag('event', 'signup');
}

notDeclared;              // ReferenceError
typeof notDeclared;       // "undefined", no error

Validate function arguments

A quick guard at the top of a function catches wrong input early, with a clear error.

javascript
function formatPrice(amount, currency = 'USD') {
  if (typeof amount !== 'number' || !Number.isFinite(amount)) {
    throw new TypeError(`amount must be a number, got ${typeof amount}`);
  }
  return new Intl.NumberFormat('en-US', { style: 'currency', currency }).format(amount);
}

Get a precise type for anything

When you need to tell dates, regexes, maps and null apart, Object.prototype.toString gives a more detailed answer.

javascript
const type = (v) => Object.prototype.toString.call(v).slice(8, -1);

type(null);         // "Null"
type([]);           // "Array"
type(new Date());   // "Date"
type(/x/);          // "RegExp"
type(new Map());    // "Map"

typeof vs instanceof

typeof checks a value’s basic type and works best for primitives. instanceof checks whether an object was created by a specific class or constructor, so it’s for objects: date instanceof Date, error instanceof TypeError. In TypeScript, both act as type guards and narrow the type inside an if. For logging what you’ve got while debugging, console.log plus typeof goes a long way; here are more ways to use console.log like a pro.

FAQ

Why does typeof null return “object”?

In the original JavaScript engine, values were stored with a type tag, and objects had the tag 0. null was the null pointer, which was also 0, so it was reported as an object. Fixing it would break existing websites, so it stays. It’s a classic interview question; try it and more in this JavaScript typeof quiz.

How do I check if a value is an array?

Array.isArray(value). typeof returns "object" for arrays.

How do I check if something is a function?

typeof value === 'function'. It works for regular functions, arrow functions, async functions and classes.

Is typeof a function?

No, it’s a unary operator, like ! or -. That’s why typeof x works without parentheses, and why it’s on the list of JavaScript reserved words.