Skip to content

TypeScript cheat sheet

TypeScript 5 syntax. Types are erased at compile time, so everything here describes shapes, not runtime behaviour.

22 entries

Basic types

let id: number = 1
let name: string = "Ada"
let ok: boolean = true

Primitives (usually inferred, so annotations are optional).

let ids: number[] = [1, 2]
let pair: [string, number] = ["a", 1]

Arrays and tuples.

let value: unknown
let anything: any
function fail(): never { throw new Error() }

unknown (safe top type), any (opt-out), never.

const dirs = ["up", "down"] as const

as const: readonly literal types.

Objects

interface User {
  id: number
  name: string
  email?: string
  readonly createdAt: Date
}

Interface with optional and readonly fields.

type Point = { x: number; y: number }

Type alias.

interface Admin extends User { role: "admin" }
type Admin2 = User & { role: "admin" }

Extending vs intersection.

type Dict = Record<string, number>
type Dict2 = { [key: string]: number }

Index signatures.

Unions & narrowing

type Id = string | number

Union type.

function len(x: string | string[]) {
  return typeof x === "string" ? x.length : x.length
}

typeof narrowing.

type Shape =
  | { kind: "circle"; r: number }
  | { kind: "square"; side: number }
function area(s: Shape) {
  switch (s.kind) {
    case "circle": return Math.PI * s.r ** 2
    case "square": return s.side ** 2
  }
}

Discriminated union.

function isUser(x: unknown): x is User {
  return typeof x === "object" && x !== null && "id" in x
}

Custom type guard.

Generics

function first<T>(arr: T[]): T | undefined { return arr[0] }

Generic function.

function getProp<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key]
}

Constraints with keyof.

interface ApiResponse<T> { data: T; error?: string }

Generic interface.

Utility types

Partial<User>  Required<User>  Readonly<User>

Make all fields optional / required / readonly.

Pick<User, "id" | "name">  Omit<User, "email">

Select or drop fields.

ReturnType<typeof fn>  Parameters<typeof fn>  Awaited<Promise<string>>

Derive types from functions and promises.

NonNullable<string | null>  Exclude<"a" | "b", "a">

Filter unions.

Handy extras

const config = { port: 3000 } satisfies Record<string, number>

satisfies checks without widening the type.

enum Level { Low = 1, High }
type Level2 = "low" | "high"

Enums (a union of literals is often simpler).

{ "compilerOptions": { "strict": true, "target": "ES2022", "module": "NodeNext", "noUncheckedIndexedAccess": true } }

tsconfig.json essentials.

Frequently asked questions

interface or type?

Both describe object shapes. Interfaces can be reopened (declaration merging) and extended; type aliases can also express unions, tuples and mapped types. Many teams use interface for objects and type for everything else.

What is the difference between any and unknown?

any turns off type checking. unknown accepts any value but forces you to narrow it (typeof, instanceof, a type guard) before using it, so it is the safe choice.

Can I run TypeScript here?

Type annotations are erased at build time, so the logic of these snippets runs as plain JavaScript. Paste the code without types into the JavaScript playground to try it.

Related cheat sheets