JavaScript typeof vs instanceof: How to Check Types Correctly

JavaScript gives you two common ways to inspect values: typeof and instanceof. They look similar at first, but they answer different questions, and using the wrong one can lead to confusing bugs in type checks, validation code, and error handling.

Quick answer: Use typeof for primitive values and functions, such as strings, numbers, booleans, and functions. Use instanceof to check whether an object comes from a particular constructor or class through its prototype chain.

Difficulty: Beginner

You'll understand this better if you know: basic JavaScript values, objects, and how functions and classes create instances.

1. What Are typeof and instanceof?

typeof is a unary operator that returns a string describing the general type of a value. instanceof is an operator that checks whether an object was created by a particular constructor function or class, or inherits from it through the prototype chain.

  • typeof answers: “What broad kind of value is this?”
  • instanceof answers: “Is this object related to this constructor or class?”
  • typeof works best with primitives and functions.
  • instanceof works best with objects.
  • They are not interchangeable, even when both seem to work in simple examples.

2. Why typeof and instanceof Matter

Type checks are common in input validation, defensive programming, library code, and debugging. If you misunderstand these operators, you may accept the wrong values, reject valid ones, or get misleading results from expressions that seem obvious.

For example, code that checks for an array with typeof value === "object" is too broad, because arrays, dates, plain objects, and null all behave differently. On the other hand, instanceof can tell you whether something is an Array or Date, but it is less reliable across different execution contexts such as iframes or separate JavaScript realms.

3. Basic Syntax

typeof syntax

Use typeof directly before a value or expression. It always returns a string.

JavaScript
typeof value

Common return values include "string", "number", "boolean", "undefined", "symbol", "bigint", "function", and "object".

instanceof syntax

Use instanceof between an object and a constructor function or class.

JavaScript
value instanceof Constructor

The result is a boolean: true or false.

4. Step-by-Step Examples

Example 1: Checking a primitive with typeof

This example shows the most natural use of typeof: checking a string.

JavaScript
const name = "Ava";

if (typeof name === "string") {
  console.log("Name is a string");
}
Output✓ Tested · Node 24
Name is a string

This works because typeof returns a simple type label for primitive values.

Example 2: Checking a class instance with instanceof

Use instanceof when you want to know whether an object was created from a specific class.

JavaScript
class User {
  constructor(name) {
    this.name = name;
  }
}

const user = new User("Ava");

if (user instanceof User) {
  console.log("This is a User instance");
}
Output✓ Tested · Node 24
This is a User instance

The check succeeds because user inherits from User.prototype.

Example 3: Distinguishing arrays from plain objects

A common beginner mistake is using typeof to detect arrays. Arrays are objects, so typeof does not identify them specifically.

JavaScript
const items = [1, 2, 3];

console.log(typeof items); // "object"
console.log(items instanceof Array); // true
Output✓ Tested · Node 24
object
true

In modern JavaScript, Array.isArray() is often the best way to check for arrays, but instanceof Array still helps you understand the relationship between an array and its constructor.

Example 4: Checking for built-in object types

instanceof is useful for objects like Date and Map.

JavaScript
const createdAt = new Date();
const settings = new Map();

console.log(createdAt instanceof Date); // true
console.log(settings instanceof Map); // true

This is a good fit when your logic depends on object behavior that comes from a specific built-in prototype.

5. Practical Use Cases

  • Validate user input before calling code that expects a string, number, or function.
  • Check whether a value is callable before invoking it as a callback.
  • Detect whether a value is a class instance in business logic or data transformation code.
  • Handle arrays separately from plain objects when normalizing API responses.
  • Write safer guard clauses in utility functions and custom validators.

6. Common Mistakes

Mistake 1: Using typeof to detect arrays

typeof cannot distinguish arrays from plain objects because arrays are objects in JavaScript.

Problem: This check treats every object-like value the same, so arrays are misidentified as generic objects.

JavaScript
const value = [1, 2];

if (typeof value === "object") {
  console.log("It is an object");
}
Output✓ Tested · Node 24
It is an object

Fix: Use Array.isArray() when you specifically want to know whether a value is an array.

JavaScript
const value = [1, 2];

if (Array.isArray(value)) {
  console.log("It is an array");
}
Output✓ Tested · Node 24
It is an array

The corrected version works because Array.isArray() is the dedicated array check.

Mistake 2: Expecting typeof null to return "null"

null is a historical JavaScript quirk. It returns "object" from typeof, which often surprises beginners.

Problem: This logic assumes null has its own type label, so the check fails to detect empty values correctly.

JavaScript
const value = null;

if (typeof value === "null") {
  console.log("No value");
}

Fix: Check value === null directly when you need to detect null specifically.

JavaScript
const value = null;

if (value === null) {
  console.log("No value");
}
Output✓ Tested · Node 24
No value

This fix works because strict equality checks the actual value instead of the typeof label.

Mistake 3: Using instanceof across different execution contexts

instanceof depends on prototype identity. Objects created in another realm, such as an iframe or a different window, may not match the constructor you expect.

Problem: An object can be a real array or date in another context and still fail instanceof in the current one, producing incorrect results.

JavaScript
const value = someValueFromAnotherWindow;

if (value instanceof Array) {
  console.log("This is an array");
}
Output✓ Tested · Node 24
Uncaught ReferenceError: someValueFromAnotherWindow is not defined

Fix: Use checks designed for cross-realm safety when possible, such as Array.isArray() for arrays or a dedicated brand check for your own data structures.

JavaScript
const value = someValueFromAnotherWindow;

if (Array.isArray(value)) {
  console.log("This is an array");
}
Output✓ Tested · Node 24
Uncaught ReferenceError: someValueFromAnotherWindow is not defined

The corrected version works better because it does not rely on constructor identity from one specific realm.

7. Best Practices

Practice 1: Use typeof for primitives and functions

typeof is the simplest and clearest tool for basic runtime checks. It is especially useful before calling a callback or handling text input.

JavaScript
function runHandler(handler) {
  if (typeof handler === "function") {
    handler();
  }
}

This keeps the check lightweight and easy to read.

Practice 2: Prefer dedicated helpers for special cases

For arrays, use Array.isArray() instead of instanceof Array when portability matters.

JavaScript
function sum(value) {
  if (!Array.isArray(value)) {
    return 0;
  }

  return value.reduce((total, item) => total + item, 0);
}

This is more robust than relying on object constructors alone.

Practice 3: Validate external data before using it

When data comes from an API, form, or untrusted source, type checks should happen before the value is used.

JavaScript
function formatAge(value) {
  if (typeof value !== "number") {
    return "Unknown age";
  }

  return `Age: ${value}`;
}

Validating early prevents later runtime errors and makes the function easier to reason about.

8. Limitations and Edge Cases

  • typeof null returns "object", which is a long-standing language quirk.
  • typeof cannot distinguish arrays, dates, and plain objects.
  • instanceof depends on the prototype chain, so objects from other realms may fail the check unexpectedly.
  • instanceof only works with callable constructors or classes on the right-hand side; using a non-constructor can throw an error.
  • Objects created with Object.create(null) do not inherit from Object.prototype, so some assumptions about object methods do not apply.
  • Subclassing affects instanceof because derived objects are also instances of their parent classes.

9. Practical Mini Project

In this mini project, we will build a small validator that classifies a value and returns a readable message. It uses typeof for primitives and instanceof for object-based checks.

JavaScript
class Product {
  constructor(name, price) {
    this.name = name;
    this.price = price;
  }
}

function describeValue(value) {
  if (value === null) {
    return "Value is null";
  }

  if (typeof value === "string") {
    return `Text with length ${value.length}`;
  }

  if (typeof value === "number") {
    return `Number: ${value}`;
  }

  if (value instanceof Product) {
    return `Product: ${value.name} costs ${value.price}`;
  }

  if (Array.isArray(value)) {
    return `Array with ${value.length} items`;
  }

  return "Unknown value type";
}

const items = [
  describeValue("hello"),
  describeValue(42),
  describeValue(new Product("Notebook", 9.99)),
  describeValue([1, 2, 3]),
  describeValue(null)
];

console.log(items);
Output✓ Tested · Node 24
[ "Text with length 5", "Number: 42", "Product: Notebook costs 9.99", "Array with 3 items", "Value is null" ]

This example shows a practical pattern: use typeof for primitives, a direct null check for null, and instanceof for class instances.

10. Key Points

  • typeof returns a string that describes broad JavaScript value categories.
  • instanceof returns a boolean based on the prototype chain.
  • typeof is best for primitives and functions.
  • instanceof is best for checking object instances created by classes or constructors.
  • null is a special case because typeof null returns "object".
  • For arrays, Array.isArray() is usually the safest choice.
  • Cross-realm objects can make instanceof less reliable.

11. Practice Exercise

  • Create a function named classifyValue.
  • If the input is a string, return "string".
  • If the input is a number, return "number".
  • If the input is an array, return "array".
  • If the input is an instance of a custom class named Book, return "book".
  • Otherwise return "unknown".

Expected output:

JavaScript
string
number
array
book
unknown

Hint: Check primitives with typeof, arrays with Array.isArray(), and class instances with instanceof.

Show solution
JavaScript
class Book {
  constructor(title) {
    this.title = title;
  }
}

function classifyValue(value) {
  if (typeof value === "string") {
    return "string";
  }

  if (typeof value === "number") {
    return "number";
  }

  if (Array.isArray(value)) {
    return "array";
  }

  if (value instanceof Book) {
    return "book";
  }

  return "unknown";
}

console.log(classifyValue("hello"));
console.log(classifyValue(12));
console.log(classifyValue([1, 2]));
console.log(classifyValue(new Book("JavaScript Guide")));
console.log(classifyValue({}));
Output✓ Tested · Node 24
string
number
array
book
unknown

12. Final Summary

typeof and instanceof solve different problems in JavaScript. typeof is the best first check for primitives, functions, and broad value categories, while instanceof helps you identify whether an object belongs to a constructor-based type.

They are both useful, but neither one is a universal type checker. null needs special handling, arrays are best checked with Array.isArray(), and cross-realm objects can make instanceof less dependable than it first appears.

When you choose the right check for the job, your validation code becomes clearer, safer, and easier to maintain. As a next step, compare these operators with Array.isArray() and Object.prototype.toString.call() so you can recognize the tradeoffs between common type-checking techniques.