thecodex.expert · The Codex Family of Knowledge
TypeScript

Union and Intersection Types

string | number means exactly what it looks like — this value is a string OR a number, and TypeScript will not let you treat it as either one until you’ve checked which.

TypeScript 6.0 | for OR, & for AND Last verified:
Canonical Definition

A union type, written with |, describes a value that could be any one of several types — TypeScript only allows operations valid on every member of the union unless the type has been narrowed first. An intersection type, written with &, combines multiple types into one that has all of their members simultaneously, commonly used to merge two separate object type shapes into a single richer one.

Union types: one of several possibilities

Without narrowing, TypeScript only permits operations valid on EVERY member of the union — calling .toUpperCase() directly would be a compile error, since a number doesn't have that method.

TypeScriptunion_types.ts
function printId(id: string | number) {
    // id.toUpperCase();   // COMPILE ERROR: number doesn't have toUpperCase
    if (typeof id === "string") {
        console.log(id.toUpperCase());   // safe: TypeScript knows id is a string here
    } else {
        console.log(id);
    }
}

Union of literal types

A union isn't limited to whole types like string or number — unioning specific literal values creates a precise, closed set of allowed values, similar in spirit to an enum but often more idiomatic in TypeScript.

TypeScriptliteral_union.ts
type Direction = "north" | "south" | "east" | "west";

function move(direction: Direction) {
    console.log(`Moving ${direction}`);
}

move("north");    // fine
// move("up");     // COMPILE ERROR: "up" is not assignable to type Direction

Intersection types: combining shapes into one

The resulting type must satisfy both original types at once — an intersection of two object types has every property from both.

TypeScriptintersection_types.ts
type HasName = { name: string };
type HasAge = { age: number };

type Person = HasName & HasAge;   // must have BOTH name and age

const p: Person = { name: "Alice", age: 30 };   // must satisfy both types
// const bad: Person = { name: "Bob" };          // COMPILE ERROR: missing 'age'

Sources

1
Microsoft. TypeScript Handbook, "Union Types" and "Intersection Types", typescriptlang.org/docs/handbook/2/everyday-types.html.