Union & Intersection Types
A union type says a value can be one of several types — this or that. An intersection type combines several types into one that has everything from all of them — this and that.
Union types
TS union.ts
function formatId(id: number | string): string { return `ID-${id}`; } console.log(formatId(42)); console.log(formatId("a9x")); console.log(formatId(true));
tsc output
union.ts:7:20 - error TS2345: Argument of type 'boolean' is not assignable to parameter of type 'string | number'.
number | string accepts either type, but nothing else — a boolean still isn't allowed, so the third call fails to compile.
Calling a method that isn't on every member
TS narrow-call.ts
function printId(id: number | string) { console.log(id.toUpperCase()); }
tsc output
narrow-call.ts:2:15 - error TS2339: Property 'toUpperCase' does not exist on type 'string | number'.
.toUpperCase() only exists on strings, not numbers — since id could be either, TypeScript refuses to allow the call at all until the code narrows id down to specifically a string first (the Type Narrowing lesson covers exactly how).
Intersection types
TS intersection.ts
interface Named {
name: string;
}
interface Aged {
age: number;
}
type Person = Named & Aged;
const p: Person = { name: "Kofi", age: 34 };
console.log(`${p.name} is ${p.age}`);
Output
Kofi is 34
Named & Aged requires both name and age to be present — an intersection adds requirements together, which is the opposite of what a union does.
Note: it's easy to mix up
| and & the first time — a union (|) actually ends up being the more restrictive one to work with day-to-day, since you can only safely call something that every member of the union has in common, while an intersection (&) gives you a type with strictly more available properties and methods, not fewer. It helps to read | as "the value could be any one of these" and & as "the value has to satisfy all of these at once."