runtime.boot

Full Stack Systems
Production Mindset

CodeWithMihir

Engineering thoughtful products from interface to infrastructure.

CodeWithMihir

TypeScript Tutorial

TypeScript Equality Narrowing Explained

Learn how equality narrowing works in TypeScript using ===, !==, ==, !=, literal types, null checks, and practical examples.

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

Equality narrowing happens when TypeScript uses comparisons like ===, !==, ==, or != to understand a more specific type.


Basic Equality Narrowing

function printValue(value: string | number) {
  if (typeof value === "string") {
    console.log(value.toUpperCase());
  } else {
    console.log(value.toFixed(2));
  }
}

This uses equality with typeof.

Inside the if, TypeScript knows value is a string.


Narrowing Literal Types

type Status = "loading" | "success" | "error";

function handleStatus(status: Status) {
  if (status === "success") {
    console.log("Show the data");
  }
}

Inside the block, TypeScript knows:

status; // "success"

The comparison narrows the union to one exact value.


Using !==

function showMessage(message: string | null) {
  if (message !== null) {
    console.log(message.toUpperCase());
  }
}

After message !== null, TypeScript knows message is a string.


Comparing Two Variables

function compare(a: string | number, b: string) {
  if (a === b) {
    console.log(a.toUpperCase());
  }
}

If a === b, then a must be a string because b is a string.

TypeScript uses that information.


Checking null and undefined Together

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

name != null removes both null and undefined.

This is a useful TypeScript pattern.


Using switch for Equality Narrowing

type Role = "admin" | "editor" | "viewer";

function getDashboard(role: Role) {
  switch (role) {
    case "admin":
      return "Admin dashboard";
    case "editor":
      return "Editor dashboard";
    case "viewer":
      return "Viewer dashboard";
  }
}

Each case narrows role to one literal value.


Common Mistake

Truthiness and equality are not the same.

function formatCount(count: number | null) {
  if (count) {
    return count.toFixed(0);
  }

  return "No count";
}

This treats 0 as missing.

Better:

function formatCount(count: number | null) {
  if (count !== null) {
    return count.toFixed(0);
  }

  return "No count";
}

Quick Recap

  • Equality checks can narrow union types.
  • Literal comparisons narrow to exact values.
  • !== null is safer than truthiness when 0 or "" are valid.
  • value != null removes both null and undefined.
  • switch statements are great for literal unions.

Next up, we will learn in Operator Narrowing →.