Master TypeScript's advanced type system features including union types, type guards, and generics.
Learn union types, literal types, type guards, and generics for powerful type-safe code.
id that can be either a string OR a number. Use the pipe symbol | to create unions:let id: string | number = 123;
id = "ABC123"; // Both are valid!type keyword to create a reusable type alias called StringOrNumber:type StringOrNumber = string | number;Direction that can ONLY be "north", "south", "east", or "west":type Direction = "north" | "south" | "east" | "west";
let heading: Direction = "north"; // OK
// heading = "up"; // ERROR: "up" is not assignableStatus with values "pending", "approved", "rejected".formatId that accepts id: string | number and returns a formatted string. Handle both types appropriately.any while maintaining flexibilityID (number): 123
ID (string): ABC-456
Formatted: ID-123
Formatted: ID-ABC-456
Direction: north
Status: approved
let id: string | number = 123;type StringOrNumber = string | number;type Direction = "north" | "south" | "east" | "west";function formatId(id: string | number): string { return "ID-" + id; }id = 123; id = "ABC"; both work!Review feedback below
processValue that takes value: string | number. Use typeof to check the type and handle each differently:function processValue(value: string | number): string {
if (typeof value === "string") {
return value.toUpperCase(); // TS knows it's string here!
} else {
return (value * 2).toString(); // TS knows it's number here!
}
}Bird (with fly(): void) and Fish (with swim(): void). Both should have a name: string property.move that takes animal: Bird | Fish. Use the in operator to check which methods exist:function move(animal: Bird | Fish): void {
if ("fly" in animal) {
animal.fly(); // TypeScript knows it's Bird
} else {
animal.swim(); // TypeScript knows it's Fish
}
}isBird that returns animal is Bird. This is a type predicate:function isBird(animal: Bird | Fish): animal is Bird {
return "fly" in animal;
}Car and Bicycle with different methods. Create a function that uses instanceof to narrow the type.Process "hello": HELLO
Process 42: 84
Sparrow is flying!
Nemo is swimming!
Is sparrow a bird? true
Car is driving at 60 mph
Bicycle is pedaling
if (typeof value === "string") { ... }if ("fly" in animal) { animal.fly(); }function isBird(a: Bird | Fish): a is Birdif (vehicle instanceof Car) { vehicle.drive(); }interface Bird { fly(): void; }Review feedback below
function identity<T>(arg: T): T {
return arg;
}
// Usage:
let num = identity<number>(42); // num is number
let str = identity<string>("hi"); // str is stringgetFirst<T> that takes an array of T and returns the first element (or undefined):function getFirst<T>(arr: T[]): T | undefined {
return arr[0];
}Box<T> interface with a contents: T property and getContents(): T method.Stack<T> class with:items: T[]push(item: T): void - add to stackpop(): T | undefined - remove and return toppeek(): T | undefined - view top without removinglength property:interface Lengthwise { length: number; }
function logLength<T extends Lengthwise>(arg: T): void {
console.log(arg.length);
}makePair<K, V> that creates an object with key and value.any)Identity number: 42
Identity string: Hello
First of [1,2,3]: 1
First of ["a","b"]: a
Box contains: TypeScript Book
Stack: pushed 1, 2, 3
Stack pop: 3
Stack peek: 2
Length of "hello": 5
Length of [1,2,3]: 3
Pair: { key: "name", value: "Alice" }
function identity<T>(arg: T): T { return arg; }interface Box<T> { contents: T; }class Stack<T> { private items: T[] = []; }function fn<T extends Lengthwise>(arg: T)function makePair<K, V>(key: K, value: V)Review feedback below