TypeScript Cheatsheet

Basics

Use this TypeScript reference while you build software engineering projects, review code, or refresh the syntax you reach for most.

Learn TypeScript From JavaScript Variables

TypeScript is JavaScript plus a static type layer, so this reference starts with the syntax you already use: let, const, functions, objects, arrays, and modules. Use it when you are trying to learn TypeScript after you learn JavaScript, or when you need a quick check while building typed software engineering projects.

let name: string = "Alice";        // mutable, block-scoped
const age: number = 30;            // immutable binding
var legacy: boolean = true;        // function-scoped (avoid; prefer let/const)

// Type inference — type is inferred when initialized
let count = 0;          // inferred: number
const label = "beta";   // inferred: string literal "beta"

Primitive Types

TypeKeywordExample
Numbernumberlet n: number = 3.14
Stringstringlet s: string = "hi"
Booleanbooleanlet b: boolean = true
BigIntbigintlet x: bigint = 9007199254740991n
Symbolsymbollet sym: symbol = Symbol("id")
Nullnulllet n: null = null
Undefinedundefinedlet u: undefined = undefined

Special Types

// any — opt out of type checking entirely (avoid when possible)
let whatever: any = 42;
whatever = "now a string"; // OK, no error

// unknown — safe top type; must narrow before use
let val: unknown = fetchData();
if (typeof val === "string") {
  console.log(val.toUpperCase()); // OK after narrowing
}

// never — represents a value that never occurs
function fail(msg: string): never {
  throw new Error(msg);
}
function infinite(): never {
  while (true) {}
}

// void — function returns undefined (or nothing)
function log(msg: string): void {
  console.log(msg);
}

// object — any non-primitive value
let obj: object = { a: 1 };

// {} — any non-null, non-undefined value (broader than object)
let notNullish: {} = 42; // valid

Type Annotations

// Variable with explicit type
let id: number;

// Function parameter and return type
function greet(name: string): string {
  return `Hello, ${name}`;
}

// Arrow function
const double = (n: number): number => n * 2;

// Array
let nums: number[] = [1, 2, 3];
let strs: Array<string> = ["a", "b"];     // generic form
let readonly: ReadonlyArray<number> = [1]; // immutable array

// Tuple — fixed-length, fixed-types
let pair: [string, number] = ["age", 25];
let named: [name: string, age: number] = ["Bob", 20]; // labeled tuple

// Optional tuple element
let triple: [string, number, boolean?] = ["x", 1];

// Rest tuple element
let rest: [string, ...number[]] = ["label", 1, 2, 3];

Type Assertions

// as syntax (preferred in all files)
const canvas = document.getElementById("c") as HTMLCanvasElement;
const len = (someValue as string).length;

// Angle-bracket syntax (NOT valid in .tsx files)
const canvas2 = <HTMLCanvasElement>document.getElementById("c");

// Double assertion — when types don't overlap (use sparingly)
const x = (value as unknown) as SpecificType;

// Non-null assertion operator ! — asserts not null/undefined
const el = document.getElementById("app")!;
el.textContent = "hello";

Literal Types and as const

// String, number, boolean literals as types
let dir: "left" | "right" = "left";
const PI: 3.14159 = 3.14159;
let flag: true = true;

// as const — narrows inferred types to literals, makes arrays readonly tuples
const config = { host: "localhost", port: 3000 } as const;
// config.host: "localhost"   config.port: 3000 (not number)

const directions = ["left", "right", "up"] as const;
// type: readonly ["left", "right", "up"]

// const enum alternative
const STATUS = { ACTIVE: "active", INACTIVE: "inactive" } as const;
type Status = typeof STATUS[keyof typeof STATUS]; // "active" | "inactive"

satisfies Operator (TS 4.9+)

// Validates a value matches a type WITHOUT widening the inferred type
type Colors = "red" | "green" | "blue";
const palette = {
  red: [255, 0, 0],
  green: "#00ff00",
} satisfies Record<Colors, string | number[]>;

palette.red;    // type: number[]   (not widened to string | number[])
palette.green;  // type: string

Type Inference

let x = [1, 2, 3];            // number[]
let fn = (a: number) => a;    // (a: number) => number
const obj = { x: 0, y: 0 };  // { x: number; y: number }

// Contextual typing — inferred from callback context
[1, 2, 3].forEach(n => console.log(n.toFixed())); // n: number

// Return type inference
function add(a: number, b: number) {
  return a + b; // inferred: number
}

typeof, keyof, instanceof

// typeof in type position — get type of a value
let s = "hello";
type T = typeof s; // string

const config = { port: 3000 };
type Config = typeof config; // { port: number }

// keyof — union of property keys
type Keys = keyof { a: number; b: string }; // "a" | "b"
type ArrayKeys = keyof string[]; // number | "length" | "push" | ...

// instanceof — narrow to class instance
if (err instanceof Error) {
  console.log(err.message); // Error
}
if (obj instanceof Map) {
  obj.get("key");
}

// typeof in runtime narrowing
function pad(val: string | number) {
  if (typeof val === "string") return val.padStart(10);
  return val.toFixed(2);
}

Destructuring with Types

// Array destructuring
const [first, second, ...rest]: number[] = [1, 2, 3, 4];

// Object destructuring with inline type
const { name, age = 25 }: { name: string; age?: number } = user;

// Rename on destructure
const { x: xPos, y: yPos }: { x: number; y: number } = point;

// Nested destructuring
const { address: { city } } = user;

// Function parameter destructuring
function display({ title, count = 0 }: { title: string; count?: number }) {
  console.log(title, count);
}

Spread and Rest

// Array spread
const a = [1, 2, 3];
const b = [...a, 4, 5]; // [1, 2, 3, 4, 5]

// Object spread (last wins on collision)
const obj1 = { x: 1, z: 0 };
const obj2 = { ...obj1, y: 2, z: 9 }; // { x: 1, z: 9, y: 2 }

// Rest parameters
function sum(...nums: number[]): number {
  return nums.reduce((a, b) => a + b, 0);
}

// Spread as arguments
const nums = [1, 2, 3] as const;
Math.max(...nums);

Optional Chaining and Nullish Operators

// Optional chaining — short-circuits on null/undefined
const city = user?.address?.city;
const first = arr?.[0];
const result = obj?.method?.();

// Nullish coalescing ?? — right side only when left is null/undefined
const name = user.name ?? "Anonymous";

// Nullish assignment
let a: number | null = null;
a ??= 42;       // assign if null/undefined: a === 42

let b = 0;
b ||= 10;       // assign if falsy: b === 10
b &&= b * 2;    // assign if truthy: b === 20

Template Literal Types

type Dir = "top" | "bottom";
type Margin = `margin-${Dir}`; // "margin-top" | "margin-bottom"

type EventName<T extends string> = `on${Capitalize<T>}`;
type ClickEvent = EventName<"click">; // "onClick"

// Intrinsic string manipulation types
type U = Uppercase<"hello">;      // "HELLO"
type L = Lowercase<"WORLD">;      // "world"
type C = Capitalize<"foo">;       // "Foo"
type N = Uncapitalize<"FooBar">;  // "fooBar"

tsconfig.json Key Options

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "exactOptionalPropertyTypes": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "outDir": "./dist",
    "rootDir": "./src"
  }
}

"strict": true enables: strictNullChecks, strictFunctionTypes, strictBindCallApply, noImplicitAny, noImplicitThis, alwaysStrict, useUnknownInCatchVariables.