Start learning free

LESSON 97 OF 675 · CONDITIONAL STATEMENTS

Union Types in TypeScript

Lesson

So far every variable had exactly one type: a string, a number, a boolean. But real programs are messier — a user ID might arrive as "abc-123" or as 42. TypeScript handles this with a union type: write the allowed types separated by | (read it as "or").

let id: string | number = "abc-123";
id = 42;      // fine — number is part of the union
id = true;    // error — boolean is NOT in the union

A string | number variable can hold either kind of value, and TypeScript tracks that for you.


The trap:

Here is where beginners get stuck. While a value's type is still the whole union, you may only use operations that are safe for every member. Strings have .length, numbers don't — so the compiler rejects this:

function describe(x: string | number): string {
    return "length is " + x.length;   // numbers have no .length!
}
error TS2339: Property 'length' does not exist on type 'string | number'.
  Property 'length' does not exist on type 'number'.

Read the second line carefully — the compiler even names the guilty member: it's number that has no .length. You WILL see this error; it means "prove which type you have first".


Narrowing with typeof:

The proof is an ordinary if. The typeof operator returns the runtime type as a string ("string", "number", ...), and TypeScript understands the check: inside the branch, the union narrows to a single type.

if (typeof x === "string") {
    // here x is a string — .length is allowed
} else {
    // only number is left — x * 2 is allowed
}

Notice the else: no second check needed. Ruling out string leaves exactly one member, so TypeScript narrows x to number automatically.


Assignment
Follow the Coding Tutorial and write a function describe(x) where x is a string | number, returning a string:

  • if x is a string, return "string of length " plus x.length,
  • otherwise, return "number doubled to " plus x * 2.

Then call it with "Algo" and with 21, printing each result with console.log, so both branches run. The exact expected output is:

string of length 4
number doubled to 42

Hint
Compare against the string "string": typeof x === "string". Writing typeof x === string (no quotes) is itself a type error.


STEP 1 OF 6
    Ctrl + Enter to check