Union Types
Union Types
Section titled “Union Types”What it is
Section titled “What it is”Union types allow a value to be one of several types. Introduced early in TypeScript, they enable flexible yet type-safe code when a value could have multiple valid types.
Before this feature
Section titled “Before this feature”Without union types, you’d use any (losing type safety):
// Loses all type checkingfunction formatValue(value: any): string { if (typeof value === "number") { return value.toFixed(2); } return value.toString();}After this feature
Section titled “After this feature”Union types maintain type safety:
// Type-safe with unionfunction formatValue(value: string | number): string { if (typeof value === "number") { return value.toFixed(2); } return value.toUpperCase(); // TypeScript knows it's a string here}
// Multiple typeslet id: string | number;id = "abc123"; // OKid = 12345; // OKid = true; // Error!
// Arrays with unionslet mixed: (string | number)[] = [1, "two", 3, "four"];
// Null/undefined unionslet userName: string | null = null;let age: number | undefined;
// Function return typesfunction getUser(id: string): User | null { return users.find(u => u.id === id) || null;}
// Type guards for narrowingfunction process(value: string | number) { if (typeof value === "string") { // TypeScript knows value is string here console.log(value.toUpperCase()); } else { // TypeScript knows value is number here console.log(value.toFixed(2)); }}Why this is better
Section titled “Why this is better”- Type safety: Better than
any, catches errors - Flexibility: Handle multiple types when needed
- Autocomplete: IDE knows possible types
- Documentation: Types serve as inline documentation
- Narrowing: Type guards refine type within blocks
Key notes / edge cases
Section titled “Key notes / edge cases”- Use type guards (
typeof,instanceof, custom guards) to narrow types - Intersection types (
A & B) are different from unions (A | B) - Can combine with type aliases for readability
- Union with
nevertype is just the other type - Order doesn’t matter in unions
// Type alias for readabilitytype ID = string | number;type Response = Success | Error;
// Discriminated unions (tagged unions)type Shape = | { kind: "circle"; radius: number } | { kind: "rectangle"; width: number; height: number };
function area(shape: Shape): number { switch (shape.kind) { case "circle": return Math.PI * shape.radius ** 2; case "rectangle": return shape.width * shape.height; }}Quick practice
Section titled “Quick practice”-
Create a variable that accepts string, number, or boolean
Answer
let value: string | number | boolean; -
Write a function that returns either a User object or null
Answer
function findUser(id: string): User | null {// implementation} -
What’s the difference between
string | numberandstring & number?Answer
`string | number` is a union (value can be string OR number). `string & number` is an intersection (impossible - a value can't be both simultaneously, results in `never`).