CTCaliberTek
Course: TypeScript Developer Path · Lesson 3 of 4Log in to track your progress and earn a certificate when you finish the course.
Programming

TypeScript Union Types, Narrowing, and Generics

Published October 14, 2026·Updated October 29, 2026·9 min read
Like SaveLog in to like, save, and track progress.

Introduction

Real data isn't always one type. Union types let a value be one of several types, narrowing lets the compiler work out which one you have at a given point, and generics let you write functions that work with many types while staying type-safe. This tutorial introduces all three.

Prerequisites

  • Interfaces and type aliases
  • Functions and arrays in TypeScript

Step-by-Step Guide

Step 1: Declare a union type

A union uses | to say a value can be any of several types. Literal types restrict a value to specific strings or numbers.

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

let current: Status = "loading";
// current = "done";
// Error: Type '"done"' is not assignable to type 'Status'.

Step 2: Narrow with type checks

Inside an if block that checks typeof, the compiler knows the narrowed type and allows operations specific to it.

function formatId(id: string | number): string {
  if (typeof id === "string") {
    return id.toUpperCase();
  }
  return id.toFixed(0);
}

Step 3: Model variants with a discriminated union

Give each variant a shared literal property. Checking it narrows the object to exactly one variant.

type Result =
  | { status: "success"; data: string }
  | { status: "error"; message: string };

function handle(result: Result): string {
  if (result.status === "success") {
    return result.data;
  }
  return result.message;
}

Step 4: Write a generic function

A type parameter such as T is a placeholder filled in by the caller's arguments, so the return type matches the input.

function firstItem<T>(items: T[]): T | undefined {
  return items[0];
}

const n = firstItem([1, 2, 3]);       // number | undefined
const s = firstItem(["a", "b"]);      // string | undefined

FAQs

What is type narrowing?
Narrowing is the compiler refining a broad type to a more specific one based on checks like typeof, equality, or property tests, so you can safely use members that only exist on the narrower type.
Why use generics instead of any?
any turns off type checking. A generic keeps the relationship between input and output types, so you retain autocomplete and compile-time safety.

Summary

Unions model values that can take several forms, narrowing makes them safe to use, and generics keep reusable code type-safe. Discriminated unions are especially useful for results and state.

Related tutorials

Comments

Log in or create a free account to join the discussion.

  • No comments yet. Be the first to comment.