Union Types

Intro to Union Types
Union types allow a value to be one of several types. They're TypeScript's way of modeling "either/or" scenariosβ€”and a core concept in functional programming.
type StringOrNumber = string | number

let value: StringOrNumber
value = 'hello' // βœ…
value = 42 // βœ…
value = true // ❌ Error

Narrowing

When you have a union type, TypeScript needs to know which specific type you're working with before you can use type-specific methods:
function process(value: string | number) {
	// Can't call .toUpperCase() yet - might be number!

	if (typeof value === 'string') {
		console.log(value.toUpperCase()) // βœ… Now TypeScript knows it's string
	} else {
		console.log(value.toFixed(2)) // βœ… Must be number
	}
}

Type Guards

Sometimes typeof checks aren't enough, especially when you need to distinguish between object shapes. Type guards are functions that tell TypeScript which type you have at runtime:
type Cat = { meow(): void }
type Dog = { bark(): void }
type Pet = Cat | Dog

function isCat(pet: Pet): pet is Cat {
	return 'meow' in pet
}

function speak(pet: Pet) {
	if (isCat(pet)) {
		pet.meow() // βœ… TypeScript knows it's Cat
	} else {
		pet.bark() // βœ… TypeScript knows it's Dog
	}
}

Discriminated Unions (Algebraic Data Types)

The most powerful pattern: objects with a common "tag" property. In functional programming, these are called algebraic data types (ADTs) or tagged unions:
type Success = { status: 'success'; data: string }
type Error = { status: 'error'; message: string }
type Result = Success | Error

function handle(result: Result) {
	if (result.status === 'success') {
		console.log(result.data) // βœ… TypeScript knows it's Success
	} else {
		console.log(result.message) // βœ… TypeScript knows it's Error
	}
}
Discriminated unions are one of TypeScript's most powerful features for making invalid states unrepresentable. By defining exactly which states are possible, you eliminate entire categories of bugs at compile time. This pattern is foundational in React, Redux, and modern functional codebases.
In this exercise, you'll master union types, narrowing, and type guards.