TypeScript Cheatsheet
TypeScript Cheatsheet
A quick reference guide for modern TypeScript (TS 5.x), covering standard types, interfaces, generics, utility types, and advanced type manipulation patterns.
Basic & Primitive Types
const isDone: boolean = false;
const score: number = 42;
const name: string = "Bob";
// Arrays & Tuples
const list: number[] = [1, 2, 3];
const listGeneric: Array<number> = [1, 2, 3];
const tuple: [string, number] = ["hello", 10]; // Fixed length, fixed types
// Special Types
let random: any = 4; // Disables all type checking (avoid)
let value: unknown = "string"; // Type-safe alternative to 'any'. Must narrow type before operations
let unusable: void = undefined; // Represent the absence of any value (commonly function returns)
let neverValue: never; // Represent values that never occur (e.g. function that throws or infinite loop)
// Type Assertions (Casts)
const rawData: unknown = "hello";
const length1 = (rawData as string).length;
const length2 = (<string>rawData).length; // Alternative syntax (avoid in JSX/TSX)
Functions
// Typing parameters & return types
function add(x: number, y: number): number {
return x + y;
}
// Arrow function typing
const multiply = (x: number, y: number): number => x * y;
// Optional and Default Parameters
const greet = (name: string, greeting?: string): string => {
return `${greeting ?? "Hello"}, ${name}!`;
};
// Rest Parameters
const sum = (base: number, ...numbers: number[]): number => {
return base + numbers.reduce((a, b) => a + b, 0);
};
// Function Type Signatures
type MathOp = (val1: number, val2: number) => number;
const divide: MathOp = (a, b) => a / b;
Interfaces vs Type Aliases
// Interfaces: Preferred for objects, supports inheritance (extends) and declaration merging
interface User {
readonly id: number; // Immutable property
name: string;
email?: string; // Optional property
}
interface Admin extends User { // Inheritance
superUser: boolean;
}
// Type Aliases: Preferred for unions, primitives, tuples, and intersections
type Point = {
x: number;
y: number;
};
type ID = string | number; // Union Type
type Point3D = Point & { z: number }; // Intersection Type
// Key Difference: Interfaces can be reopened to add properties (declaration merging)
interface User {
phoneNumber?: string;
}
Classes & Access Modifiers
class Developer {
public name: string; // Accessible anywhere (default)
protected age: number; // Accessible within this class and subclasses
private id: number; // Accessible only within this class
constructor(name: string, age: number, id: number) {
this.name = name;
this.age = age;
this.id = id;
}
}
// Constructor Parameter Shorthand (Concise alternative)
class CleanDeveloper {
constructor(
public name: string,
protected age: number,
private id: number,
public readonly created: Date = new Date()
) {}
}
Union, Intersection & Enums
// Union Types
type NetworkState = "loading" | "failed" | "success";
// Intersection Types
interface ErrorState { error: string }
interface SuccessState { data: object }
type CombinedState = ErrorState & SuccessState;
// Numeric Enums
enum Direction { Up = 1, Down, Left, Right } // Down = 2, Left = 3, Right = 4
// String Enums (Recommended over numeric for readability)
enum LogLevel {
Info = "INFO",
Warn = "WARN",
Error = "ERROR"
}
Type Guards & Narrowing
// 1. typeof (Narrow primitives)
function printId(id: string | number) {
if (typeof id === "string") {
console.log(id.toUpperCase());
} else {
console.log(id.toFixed(2));
}
}
// 2. instanceof (Narrow classes)
class FileLogger { log() { console.log("file"); } }
class DBLogger { log() { console.log("db"); } }
function executeLog(logger: FileLogger | DBLogger) {
if (logger instanceof FileLogger) {
logger.log();
}
}
// 3. 'in' Operator (Narrow structures)
type Fish = { swim: () => void };
type Bird = { fly: () => void };
function move(animal: Fish | Bird) {
if ("swim" in animal) {
animal.swim();
}
}
// 4. Custom Type Guard (User-defined type predicates)
function isFish(animal: Fish | Bird): animal is Fish {
return (animal as Fish).swim !== undefined;
}
Generics
// Generic Functions
function identity<T>(arg: T): T {
return arg;
}
const output = identity<string>("myString");
// Generic Interfaces
interface KeyValuePair<K, V> {
key: K;
value: V;
}
const kv: KeyValuePair<number, string> = { key: 1, value: "Node" };
// Generic Constraints
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // Safe: we know T has a .length property
return arg;
}
Built-in Utility Types
interface Todo {
title: string;
description: string;
completed: boolean;
}
// Partial<T>: Makes all properties optional
const updateTodo = (todo: Todo, fieldsToUpdate: Partial<Todo>) => ({ ...todo, ...fieldsToUpdate });
// Required<T>: Makes all properties required
type StrictTodo = Required<Todo>;
// Readonly<T>: Makes all properties immutable
const myTodo: Readonly<Todo> = { title: "Test", description: "Desc", completed: false };
// myTodo.title = "New"; // Error: Cannot assign to 'title' because it is a read-only property
// Record<K, T>: Creates an object type with keys K and value type T
const roles: Record<string, string[]> = {
admin: ["create", "delete"],
user: ["read"]
};
// Pick<T, K>: Extracts a subset of properties K from T
type TodoPreview = Pick<Todo, "title" | "completed">;
// Omit<T, K>: Removes a subset of properties K from T
type TodoInfo = Omit<Todo, "completed">;
// ReturnType<T>: Obtains the return type of a function type
const makeUser = () => ({ name: "Alice", id: 10 });
type UserObject = ReturnType<typeof makeUser>; // { name: string, id: number }
Advanced Type Operators
interface Car {
make: string;
model: string;
year: number;
}
// keyof: Creates a union of object keys
type CarKeys = keyof Car; // "make" | "model" | "year"
// Lookup Types (Indexed Access)
type YearType = Car["year"]; // number
// Mapped Types
type ReadOnlyMapped<T> = {
readonly [P in keyof T]: T[P];
};
type ReadOnlyCar = ReadOnlyMapped<Car>;
// Conditional Types
type IsString<T> = T extends string ? true : false;
type A = IsString<string>; // true
type B = IsString<number>; // false
// Template Literal Types
type EventName<T extends string> = `on${Capitalize<T>}`;
type ClickEvent = EventName<"click">; // "onClick"