runtime.boot

Full Stack Systems
Production Mindset

CodeWithMihir

Engineering thoughtful products from interface to infrastructure.

CodeWithMihir

TypeScript Tutorial

TypeScript typeof Narrowing Explained

Learn how typeof narrowing works in TypeScript for strings, numbers, booleans, undefined, functions, objects, and common mistakes.

Welcome back! I am Mihir, and in this lesson we will learn typeof narrowing in TypeScript.

typeof is one of the simplest ways to narrow primitive union types.


Basic typeof Narrowing

function format(value: string | number) {
  if (typeof value === "string") {
    return value.toUpperCase();
  }

  return value.toFixed(2);
}

Inside the first block, value is a string.

After that block, value is a number.


typeof with Boolean

function describe(value: string | boolean) {
  if (typeof value === "boolean") {
    return value ? "Yes" : "No";
  }

  return value.trim();
}

TypeScript narrows value based on the result of typeof.


typeof with undefined

function greet(name?: string) {
  if (typeof name === "undefined") {
    return "Hello, guest";
  }

  return `Hello, ${name.toUpperCase()}`;
}

After checking for undefined, TypeScript knows name is a string.


typeof with Functions

function run(value: string | (() => string)) {
  if (typeof value === "function") {
    return value();
  }

  return value;
}

typeof value === "function" narrows the value to a callable function.


typeof Results

Common typeof results include:

  • "string"
  • "number"
  • "boolean"
  • "undefined"
  • "function"
  • "object"
  • "symbol"
  • "bigint"

These strings are what TypeScript uses for narrowing.


Be Careful with null

In JavaScript:

typeof null;

The result is:

"object"

So this check is not enough:

function printName(user: { name: string } | null) {
  if (typeof user === "object") {
    console.log(user.name);
  }
}

user could still be null.

Better:

function printName(user: { name: string } | null) {
  if (user !== null) {
    console.log(user.name);
  }
}

typeof Does Not Check Object Shapes

type User = {
  name: string;
};

function print(value: User | string) {
  if (typeof value === "object") {
    console.log(value.name);
  }
}

This works for this simple union, but typeof only tells you that the value is an object. It does not verify every property.

For object shapes, other narrowing techniques are often better.


Quick Recap

  • typeof is great for primitive narrowing.
  • It works with strings, numbers, booleans, undefined, functions, symbols, and bigint.
  • Be careful because typeof null is "object".
  • typeof does not deeply validate object structure.

Next up, we will learn Truthiness Narrowing →.