Union types allow a value to hold one of several types, and checks narrow the current type.

union type A union such as `number | string` accepts either type until a check narrows the value.

Union Narrowing

input
union.ts
Replay: real traced execution (multi-file project)
let input: number | string = "42";

let value: number;
if (typeof input === "string") {
    value = Number(input);
    console.log(`parsed ${input}`);
} else {
    value = input;
    console.log(`used number ${input}`);
}

const doubled: number = value * 2;
console.log(`doubled=${doubled}`);
let input: number | string = 7;

let value: number;
if (typeof input === "string") {
    value = Number(input);
    console.log(`parsed ${input}`);
} else {
    value = input;
    console.log(`used number ${input}`);
}

const doubled: number = value * 2;
console.log(`doubled=${doubled}`);
let input: number | string = "18";

let value: number;
if (typeof input === "string") {
    value = Number(input);
    console.log(`parsed ${input}`);
} else {
    value = input;
    console.log(`used number ${input}`);
}

const doubled: number = value * 2;
console.log(`doubled=${doubled}`);
  1. input ← 42, value ← undefined

    1let input→ 42: number | string = "42";  //@input=7, "18"23let value→ undefined: number;4if (typeof input === "string") {
  2. if (typeof input === "string")

    3let value: number;4if (typeof input === "string") {5    value = Number(input42);6    console.log(`parsed ${input42}`);7} else {
    outputparsed 42
  3. doubled ← 84, value ← 42

    9    console.log(`used number ${input}`);10}1112const doubled→ 84: number = value→ 42 * 2;13console.log(`doubled=${doubled84}`);
    outputdoubled=84
  1. input ← 7, value ← undefined

    1let input→ 7: number | string = 7;23let value→ undefined: number;4if (typeof input === "string") {
  2. else

    6    console.log(`parsed ${input}`);7} else {8    value = input7;9    console.log(`used number ${input7}`);10}
    outputused number 7
  3. doubled ← 14, value ← 7

    9    console.log(`used number ${input}`);10}1112const doubled→ 14: number = value→ 7 * 2;13console.log(`doubled=${doubled14}`);
    outputdoubled=14
  1. input ← 18, value ← undefined

    1let input→ 18: number | string = "18";23let value→ undefined: number;4if (typeof input === "string") {
  2. if (typeof input === "string")

    3let value: number;4if (typeof input === "string") {5    value = Number(input18);6    console.log(`parsed ${input18}`);7} else {
    outputparsed 18
  3. doubled ← 36, value ← 18

    9    console.log(`used number ${input}`);10}1112const doubled→ 36: number = value→ 18 * 2;13console.log(`doubled=${doubled36}`);
    outputdoubled=36

Follow the Check

  1. input starts as number | string.
  2. typeof input === "string" chooses the string branch.
  3. The string branch parses "42" into a number.
  4. The number branch can use the value directly.
  5. After either branch, value is a number and can be doubled. | Current input | Check result | Next value | | --- | --- | --- | | "42" | string branch | Number(input) | | 7 | number branch | input |

Exercise: union.ts

Handle number or string input by parsing strings, using numbers directly, and printing the doubled result