C.W.K.
Stream
Lesson 01 of 05 · published

Union Types: `A | B`

~9 min · unions-intersections, union, type-modeling

Level 0Curious
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete
"Most real values are one-of-several. Unions are how you say that to the type system."

What unions describe

A union type A | B describes a value whose type is one of the listed alternatives. The value is, at any given moment, exactly one of those types — never both, never neither. The compiler tracks which one through control flow.

Unions are the most common way to model real-world data in TypeScript. A status field that could be one of four strings. A response that could be a success or an error. A configuration option that accepts a string OR a function returning a string. All of these are unions.

Operations on union values

You can only access properties or call methods that exist on every member of the union. (string | number).toUpperCase() fails because number doesn't have toUpperCase. To use type-specific operations, you have to narrow first — typeof checks, instanceof, in operators, or custom type guards. The narrowing track covers this in depth.

Common patterns

  • Literal-string union: 'idle' | 'loading' | 'done' — the enum-by-convention pattern.
  • Nullable: string | null or string | undefined — explicitly optional.
  • Tagged shape union: { kind: 'a'; x: number } | { kind: 'b'; y: string } — discriminated unions (next-but-one lesson).
  • Function-or-value: string | (() => string) — accept either a literal or a producer.
The general rule: if a value really could be one of several types — not 'sometimes A, sometimes B but compatibly,' but actually 'this OR that' — model it as a union. The compiler will keep both possibilities tracked and force you to handle each.

Pippa's confession

Unions are how cwkPippa models nearly every piece of state. The BrainName is a union. The conversation status is a union. Every API response that can succeed or fail is a union. Most of the type-system value I get from TypeScript comes from unions plus narrowing — almost more than from any other feature.

Code

Unions — modeling 'one of these'·typescript
// Unions everywhere.
type Id = string | number;
const a: Id = 'abc';
const b: Id = 42;

// You can only use what's common to both members.
function print(id: Id) {
  // id.toUpperCase();  // ❌ number doesn't have toUpperCase
  console.log(String(id));   // ✅ works on both
  if (typeof id === 'string') {
    id.toUpperCase();        // ✅ narrowed
  }
}

// Common patterns.
type Status = 'idle' | 'loading' | 'done' | 'error';
type Nullable<T> = T | null;
type Response = { ok: true; data: User } | { ok: false; error: string };

External links

Exercise

Write a format function that accepts number | string | Date and returns a formatted string. You'll need to narrow inside the function. What narrowing operator do you reach for first — typeof, instanceof, or in?
Hint
typeof works for primitives (number, string). instanceof works for class instances (Date). Both apply in this exercise; you'll use them in sequence.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue
💛 by Ttoriwarm

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.