A union type (A | B) allows a value to be one of several types; an intersection type (A & B) combines multiple types into one that has all their members.
Unions model 'either/or': type Id = string | number, or a discriminated union type Result = { ok: true; data: X } | { ok: false; error: string }. Before using a union value you must NARROW it (typeof, in, or a discriminant field) so TypeScript knows which member you have. Intersections model 'and': type Admin = User & { permissions: string[] } produces a type with all User fields PLUS permissions. Discriminated unions (a shared literal tag like ok) are a powerful pattern for modeling API responses and state, letting the compiler exhaustively check each case.
Typing an API result as a discriminated union type Resp = { status: 'success'; data: User } | { status: 'error'; message: string } lets a test switch on resp.status and get the right fields type-safely in each branch.
function pay(id: string | number) — accessing id.toUpperCase() errors. Why, and how do you fix it?