liveBook · Manning

Union type

As explained in Essential TypeScript 5, Third Edition

A union type is a TypeScript type that allows a value to conform to any one of multiple constituent types and exposes only members shared by those types.

A union type lets a value have any one of several types without giving up type checking. Write `string | number` to accept either type. Unlike `any`, a union limits the values that can be assigned and the operations that can be performed. section 7.3

A result with two possible types

In `src/index.ts`, `function calculateTax(amount: number, format: boolean): string | number` returns a formatted string when `format` is true and a number otherwise. Both calls still have the declared `string | number` result type: the compiler does not infer a narrower result from the boolean argument. A union can contain more than two types. section 7.3

Treat a union as a type in its own right. Before narrowing, use only members available on every constituent type. A `string | number` value has `toString`, but calling `toFixed` or `charAt` directly produces a compiler error because each belongs to only one constituent. section 7.3

Use a runtime check when you need a constituent’s members: `if (typeof value === "number") { console.log(value.toFixed(2)); }`. An `as number` assertion also changes what the compiler permits, but it does not convert or check the runtime value. An assertion to an unrelated type, such as `boolean` for `string | number`, is normally rejected. section 7.4 section 7.4.1

With `strictNullChecks` enabled, include `null` explicitly when it is a possible result: `string | number | null`. Test `value !== null` before using the remaining union. A trailing `!` removes null from the compiler’s view without a runtime check; use it only when null cannot occur, or a runtime error may follow. section 7.7.1 section 7.7.2 section 7.7.3

Objects in one array

For `Product | Person`, both object types define `id` and `name`, so an array item can be read through those properties without narrowing. `price` and `city` are not available on the union. Because the types disagree about `id`, its property type is `number | string`; their shared `name` remains `string`. section 10.2.4 section 10.2.5

Listing 10.12 Using a type union in the index.ts file in the src folder
type Product = {
    id: number,
    name: string, 
    price?: number
};

type Person = {
    id: string,
    name: string, 
    city: string
};

let hat = { id: 1, name: "Hat", price: 100 };
let gloves = { id: 2, name: "Gloves", price: 75 };
let umbrella = { id: 3, name: "Umbrella", price: 30 };
let bob = { id: "bsmith", name: "Bob", city: "London" };
 
let dataItems: (Product | Person)[] = [hat, gloves, umbrella, bob];

dataItems.forEach(item => 
    console.log(`ID: ${item.id}, Name: ${item.name}`));

The complete `src/index.ts` listing shows the two object shapes, their union-typed array, and access to shared properties. section 10.2.4

A union describes possibilities, not every relationship between them. A function accepting `number | null` and returning `number | null` does not tell callers that a number argument always produces a number. Function type overloads can express that mapping. Likewise, a collection typed for `Person | Product` can contain both; use a generic type parameter when each collection should retain its own item type. section 8.2.4 section 12.2.1

Unions also combine literal values with ordinary types: `string | true | 3` accepts any string, but only those specified boolean and number values. In JavaScript files, a JSDoc parameter annotation such as `{ number | string }` can describe the same choice to the TypeScript compiler. section 9.5.2 section 15.3.1

How Essential TypeScript 5, Third Edition covers it

How deep it goes
Works through syntax, shared members, property types, narrowing, nullable values, and limits that motivate overloads or generics.
Examples
Uses a tax function returning strings or numbers, nullable tax results, and an array mixing objects with shared properties.
What it assumes
Assumes familiarity with JavaScript values and functions while introducing TypeScript union syntax and its type-checking behavior.
What you can do after
Build it from scratch: annotate mixed values and safely access constituent-specific members after narrowing.
How it connects
Connects type annotations and inference to type guards, assertions, strict null checks, object shapes, function overloads, and generics.

Also explained in

Compare how 10 books explain union type →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Essential TypeScript 5, Third Edition. The section links point to the parts of the book it draws on.