Skip to the content.

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"