Chapter 26: TypeScript Type Guards

TypeScript Type Guards very calmly and thoroughly, like we’re sitting together with VS Code open, slowly typing examples, and understanding exactly why this feature feels magical when you first “get it”.

Type Guards are one of the most important and most frequently used advanced features in real TypeScript code — especially in 2025–2026 when dealing with APIs, forms, state, unions, unknown, any, third-party data, etc.

1. The core idea in one honest sentence

A type guard is a runtime check that tells the TypeScript compiler: “After this check passes, I now know more about the type — please narrow it down for the rest of this block.”

It’s a bridge between runtime reality and compile-time safety.

Without type guards → you are forced to use as assertions everywhere (dangerous). With type guards → TypeScript narrows the type automatically in the true branch.

2. The four most common kinds of type guards (in order of how often you’ll use them)

A. typeof checks (the simplest & most frequent)

TypeScript

Very common when:

  • Dealing with form inputs (string | number)
  • API responses (unknown → narrow to string / number / object)
  • Union types with primitives

B. instanceof checks (for classes)

TypeScript

Very common when:

  • Working with class hierarchies
  • DOM elements (HTMLElement vs HTMLInputElement)
  • Custom error classes (AppError vs ValidationError)

C. Property / key existence checks (in operator)

TypeScript

Very common when:

  • Discriminated unions (see next point)
  • Optional / variant object shapes
  • JSON / API data that sometimes has extra fields

D. Discriminated unions + literal property check (the king in 2026)

This is the most powerful and most used pattern in modern TypeScript.

TypeScript

Key requirements for discriminated union narrowing:

  • A literal property (usually called kind, type, status, _tag, tag, etc.)
  • The property has literal types (“success” | “error”, not just string)
  • All members of the union have the same property name

3. User-defined / custom type guards (when built-in checks are not enough)

TypeScript

Modern style (TS 5.5+ inferred type predicates)

TypeScript

Very common in:

  • Form validation
  • API response parsing (before Zod/valibot)
  • State / Redux action narrowing
  • Third-party library data

4. Quick reference table (keep this in your mind)

Guard type Syntax example Narrows to… Most common use-case
typeof typeof x === “string” string / number / boolean / … Primitives, form values, unknown → primitive
instanceof x instanceof Error specific class Custom errors, DOM nodes
in operator “age” in obj object with that property Optional fields, variant shapes
Discriminated union res.kind === “loading” matching union member State machines, API results, Redux actions
Custom type guard isUser(obj): obj is User whatever you declare Complex runtime checks, parsing

5. Very common real-world patterns in 2026

Pattern 1: API fetch with unknown → narrowed

TypeScript

Pattern 2: Loading / Success / Error state (very frequent)

TypeScript

6. Mini homework (try in playground today)

  1. Write a function processInput(value: unknown) that:
    • If string → uppercase and log length
    • If number → toFixed(2)
    • If array of strings → join with “, “
    • Else → “Unknown type”
  2. Create a discriminated union for Result<T> (success/error) and narrow it
  3. Write a custom guard isPerson(value: unknown): value is {name: string, age: number}

Any part confusing or want to go deeper?

  • How type guards work with generics
  • Combining guards with && / ||
  • Type predicates vs assertion functions
  • Real tRPC / Zod narrowing patterns
  • Common mistakes people still make

Just tell me — we’ll zoom in exactly where you need it! 😄

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *