TypeScript Union Types

Union types are used when a value can be more than a single type.

Such as when a property would be string or number

function printStatusCode(code: string | number) {
console.log(`My status code is ${code}.`)
}
// Function accepts both string or number
printStatusCode(404);
printStatusCode('404');

But you need a type checking before you can call a specific property/method which is not included in all types

function printStatusCode(code: string | number) {
console.log(`My status code is ${code.toUpperCase()}.`)
// Error TS2339: Property 'toUpperCase' does not exist on type 'string | number'.
// Property 'toUpperCase' does not exist on type 'number'.
}

Discriminated Unions

If you have a class with a literal member then you can use that property to discriminate between union members

interface Square {
kind: "square";
size: number;
}

interface Rectangle {
kind: "rectangle";
width: number;
height: number;
}
type Shape = Square | Rectangle;

If you use a type guard style check (==, ===, !=, !==) or switch on the discriminant property (here kind) TypeScript will realize that the object must be of the type that has that specific literal and do a type narrowing for you

function area(s: Shape) {
if (s.kind === "square") {
// Now TypeScript *knows* that `s` must be a square ;)
// So you can use its members safely :)
return s.size * s.size;
}
else {
// Wasn't a square? So TypeScript will figure out that it must be a Rectangle ;)
// So you can use its members safely :)
return s.width * s.height;
}
}