TypeScript Cheatsheet

Basics

Use this TypeScript reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

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.