Cheat Sheet Library

JavaScript & TypeScript Cheat Sheet

Modern JavaScript (up to ES2025) for browsers and Node.js, then TypeScript (5.x to 7.0) on top: types, generics, narrowing and project setup. Tags like (ES2022) show when a feature arrived; everything here runs in current browsers and Node 22+.

  • 158 entries
  • 14 sections
  • Updated

158 entries

On this page

Variables, Types & Operators #

CodeWhat it does
const max = 10Constant binding: use by default (objects stay mutable)
let count = 0Variable you can reassign; block-scoped like const
var xOld function-scoped variable: don't use in new code
typeof x"string", "number", "boolean", "undefined", "object", "function", "bigint", "symbol"
typeof null"object" (historic bug): test with x === null
Array.isArray(x)The reliable way to detect an array
a === b / a !== bStrict equality without type conversion (avoid ==)
user?.address?.cityOptional chaining: undefined instead of a crash (ES2020)
obj.method?.()Call only if the method exists
a ?? bb only when a is null or undefined (ES2020)
a || bb when a is falsy: 0, "", false, null, undefined, NaN
x ??= 5 / x ||= 5 / x &&= f(x)Logical assignment (ES2021)
cond ? a : bTernary: inline if/else
2 ** 10Exponent: 1024

Strings & Numbers #

CodeWhat it does
`Hi ${name}!`Template literal: insert values, may span lines
s.includes("x") / s.startsWith("x") / s.endsWith("x")Contains / begins with / ends with
s.slice(1, 4) / s.slice(-3)Substring (negative counts from the end)
s.split(",") / arr.join(", ")String to array and back
s.trim() / s.toUpperCase() / s.toLowerCase()Strip whitespace / change case
s.replaceAll("a", "b")Replace every match (ES2021); replace does only the first
s.padStart(3, "0")"7" becomes "007"
Number("42") / parseInt("42px", 10)Convert: Number("42px") is NaN, parseInt gives 42
Number.isNaN(x) / Number.isInteger(x)Reliable number checks
n.toFixed(2)3.14159 becomes the string "3.14"
0.1 + 0.20.30000000000000004: floats are imprecise, store money in cents
Math.round(x) / Math.floor(x) / Math.ceil(x)Round / down / up
Math.max(...nums)Largest value of an array (spread it into arguments)
Math.floor(Math.random() * 6) + 1Random integer from 1 to 6
1_000_000 / 123nNumeric separator (ES2021) / BigInt for huge integers
n.toLocaleString("nl-BE")1234.5 becomes "1.234,5"

Arrays #

CodeWhat it does
a.push(x) / a.pop()Add / remove at the end (unshift / shift at the start)
a.map(x => x * 2)New array with every item transformed
a.filter(x => x > 1)New array with the items that pass
a.reduce((sum, x) => sum + x, 0)Combine into one value (always give a start value)
a.find(fn) / a.findIndex(fn)First match / its index (undefined / -1 if none); findLast (ES2023)
a.some(fn) / a.every(fn)At least one / all items pass
a.includes(2) / a.indexOf(2)Contains the value / its position or -1
a.at(-1)Last item (ES2022), also works on strings
a.slice(1, 3) / a.splice(i, 1)Copy a part / remove 1 item at index i (mutates)
a.flat() / a.flatMap(fn)Flatten one level / map then flatten (ES2019)
a.toSorted((x, y) => x - y)Sorted copy, numbers ascending (ES2023); sort mutates
a.toReversed() / a.with(0, "x")Reversed copy / copy with one item replaced (ES2023)
[...a, ...b]Copy or merge arrays
const [first, , third, ...rest] = aDestructuring (skip items with commas)
Array.from({ length: 3 }, (_, i) => i)Build an array: [0, 1, 2]
Object.groupBy(a, x => x.type)Group into an object of arrays (ES2024)

Objects #

CodeWhat it does
const user = { name, age }Shorthand for { name: name, age: age }
{ [key]: value }Computed property name
const { name, role = "user" } = userDestructure with a default value
const { name: userName } = userDestructure and rename
const { password, ...safe } = userRest: everything except password
{ ...defaults, ...options }Shallow merge (later keys win)
Object.keys(o) / Object.values(o) / Object.entries(o)Keys / values / [key, value] pairs
Object.fromEntries(pairs)Pairs back to an object (ES2019)
Object.hasOwn(o, "key") / "key" in oOwn property (ES2022) / own or inherited
structuredClone(o)Deep copy, including Dates, Maps and Sets (not functions)
Object.freeze(o)Make read-only (shallow)

Control Flow & Functions #

CodeWhat it does
if (a) {} else if (b) {} else {}Conditions
switch (v) { case 1: ...; break; default: ... }One value against many cases (don't forget break)
for (const item of items)Loop over values (arrays, strings, Maps, Sets)
for (const [i, item] of items.entries())Values with their index
for (const key in obj)Loop over object keys (not for arrays)
for (let i = 0; i < n; i++) / while (cond) {}Counting loop / loop while true
break / continueLeave the loop / skip to the next round
function add(a, b) { return a + b; }Declaration (hoisted: usable before its line)
const add = (a, b) => a + bArrow function with implicit return (no own this)
const make = () => ({ id: 1 })Arrow returning an object: wrap it in ()
function greet(name = "guest")Default parameter
function sum(...nums)Rest parameter: all arguments as an array
function draw({ x, y })Destructure an object parameter
const counter = () => { let n = 0; return () => ++n; }Closure: the inner function keeps its own private n

Classes & Modules #

class Animal {
  static count = 0;           // static field (ES2022)
  #secret = "hidden";         // truly private field (ES2022)
  sound = "...";              // public field
  constructor(name) { this.name = name; Animal.count++; }
  speak() { return `${this.name} says ${this.sound}`; }
  get secretLength() { return this.#secret.length; }
}
class Dog extends Animal {
  sound = "woof";
  speak() { return super.speak() + "!"; }
}
new Dog("Rex").speak();       // "Rex says woof!"
CodeWhat it does
export const PI = 3.14Named export (as many as you like)
export default function App() {}Default export (one per file)
import { PI, area } from "./math.js"Named import: names must match, keep the .js
import App from "./App.js"Default import: pick any name
import { PI as pi } from "./math.js"Rename on import
import * as math from "./math.js"Everything as one object
const { chart } = await import("./chart.js")Dynamic import: load code on demand
"type": "module"In package.json: .js files in Node are ES modules

Promises, Async & Errors #

async function getUser(id) {
  const res = await fetch(`/api/users/${id}`);
  if (!res.ok) throw new Error(`HTTP ${res.status}`); // 404/500 don't reject!
  return res.json();
}
try {
  const user = await getUser(1);
} catch (err) {
  console.error("Failed:", err.message);
} finally {
  spinner.hidden = true;      // runs either way
}
CodeWhat it does
await pWait inside an async function, or at the top level of a module (ES2022)
Promise.all([p1, p2])Run in parallel; rejects as soon as one fails
Promise.allSettled([p1, p2])Wait for all: { status, value } or { status, reason } each (ES2020)
Promise.any([p1, p2])First success; rejects only if all fail (ES2021)
Promise.race([p1, p2])First to finish, success or failure
new Promise((resolve, reject) => {})Wrap callback-style code
const sleep = ms => new Promise(r => setTimeout(r, ms))Delay helper: await sleep(500)
fetch(url, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data) })Send JSON
fetch(url, { signal: AbortSignal.timeout(5000) })Give up after 5 seconds
throw new Error("Save failed", { cause: err })Wrap an error, keep the original (ES2022)
err instanceof TypeErrorCheck the error type in catch

Map, Set, JSON & Dates #

CodeWhat it does
const m = new Map()Key-value store: any key type, keeps insertion order
m.set(k, v) / m.get(k) / m.has(k) / m.delete(k)Basic Map operations (m.size = count)
const s = new Set([1, 2, 2])Unique values: {1, 2} (add, has, delete, size)
[...new Set(arr)]Remove duplicates from an array
a.union(b) / a.intersection(b) / a.difference(b)Set math, returns a new Set (ES2025)
JSON.stringify(obj, null, 2)To a JSON string, pretty-printed with 2 spaces
JSON.parse(text)JSON string to value (throws on invalid JSON)
new Date() / Date.now()Now, as a Date / in milliseconds since 1970
new Date("2026-10-11T09:30:00")Parse ISO text (no Z at the end = local time)
d.getFullYear() / d.getMonth() / d.getDate()Year / month (0 = January) / day of month
d.toISOString()Always UTC: 09:30 in Brussels gives "2026-10-11T07:30:00.000Z"
d.toLocaleDateString("nl-BE")Local format: "11/10/2026"

DOM Basics #

CodeWhat it does
document.querySelector(".card")First element matching a CSS selector (or null)
document.querySelectorAll("li")All matches as a NodeList (works with for...of)
el.addEventListener("click", e => {})Run code on an event
e.preventDefault() / e.targetStop default behaviour (form submit) / element that fired
el.classList.add("on") / .remove("on") / .toggle("on")Manage CSS classes (.contains to test)
el.dataset.userIdReads the data-user-id attribute
el.textContent = textSet text safely: HTML is not parsed
el.innerHTML = htmlParse HTML: never with user input (XSS risk)
document.createElement("li")Create a new element
parent.append(child) / el.remove()Insert / remove an element
input.valueCurrent value of a form field (always a string)

TypeScript Basics #

CodeWhat it does
let title: string = "Hi"Type annotation
let count = 0Inferred as number: annotate only where inference can't help
number[] / Array<number>Array of numbers
[string, number]Tuple: fixed length and types
function add(a: number, b: number): numberParameter and return types
(x: number) => stringFunction type
string | numberUnion: one of these types
A & BIntersection: has everything from both
"sm" | "md" | "lg"Literal types: only these exact values
email?: string / readonly id: numberOptional / cannot be reassigned
unknown / anyMust narrow before use (safe) / switches checking off (avoid)
void / neverReturns nothing / never returns (always throws)
value as User / value!Assertion / "not null": no runtime check, use sparingly
interface User {               // object shapes; can extend and be merged
  readonly id: number;
  name: string;
  email?: string;
}
interface Admin extends User { role: "admin" }
type ID = string | number;     // type alias: also unions, tuples, primitives
type Point3D = { x: number; y: number } & { z: number };

Generics & Utility Types #

function first<T>(items: T[]): T | undefined { return items[0]; }
first([1, 2]);                 // T is inferred as number
interface ApiResponse<T> { data: T; error?: string }
function longest<T extends { length: number }>(a: T, b: T): T {
  return a.length >= b.length ? a : b;
}
CodeWhat it does
Partial<User> / Required<User>All properties optional / required
Readonly<User>All properties read-only
Pick<User, "id" | "name">Only these keys
Omit<User, "email">Everything except these keys
Record<string, number>Object with these key and value types
ReturnType<typeof fn> / Parameters<typeof fn>Return type / parameter types (tuple) of a function
Awaited<Promise<User>>The resolved type: User
NonNullable<T>Removes null and undefined
Exclude<T, U> / Extract<T, U>Remove / keep union members
keyof UserUnion of the keys: "id" | "name" | "email"
typeof config / User["name"]Type of a value / type of one property

Narrowing & Type Tricks #

CodeWhat it does
typeof x === "string"Narrow primitives
"swim" in petNarrow by property
err instanceof ErrorNarrow class instances (e.g. in catch)
x != nullRemoves both null and undefined
function isUser(x: unknown): x is UserCustom type guard
as constReadonly, exact literal types
satisfies TypeCheck against a type but keep the precise inferred type (TS 4.9+)
enum Role { Admin, User }Enum: emits runtime code, Node's type stripping can't run it
type Role = "admin" | "user"Union of literals: usually preferred over enums
type Shape = { kind: "circle"; radius: number } | { kind: "rect"; w: number; h: number };
function area(s: Shape): number {
  switch (s.kind) {            // discriminated union: TS narrows per case
    case "circle": return Math.PI * s.radius ** 2;
    case "rect": return s.w * s.h;
    default: { const missing: never = s; return missing; } // error if a case is missing
  }
}
const ROLES = ["admin", "editor"] as const;
type Role = (typeof ROLES)[number];            // "admin" | "editor"
const config = { port: 3000 } satisfies Record<string, string | number>;
config.port.toFixed();                         // still number, not string | number

TypeScript Setup & Running #

CodeWhat it does
npm i -D typescriptInstall the compiler in the project
npx tsc --initCreate a tsconfig.json with good defaults
npx tsc / npx tsc --noEmitCompile to JS / only type-check (--watch to repeat on save)
"strict": trueAll strict checks incl. null checks (default since TS 6.0, older projects must set it)
"target": "ES2022"JavaScript version to output
"module": "NodeNext"Node's module rules; with Vite and other bundlers use "ESNext" + "moduleResolution": "bundler"
"noUncheckedIndexedAccess": truearr[i] becomes T | undefined
"erasableSyntaxOnly": trueForbid enums, namespaces etc. so Node can strip types (TS 5.8+)
node app.tsRun TS directly: Node strips types without checking them (Node 22.18+ / 23.6+)
node --experimental-strip-types app.tsSame on older Node 22 versions
npx tsx app.tsRun any TS, including enums (tsx watch restarts on save)
import type { User } from "./types.ts"Type-only import, removed at runtime

Tips #

  • Default to const and ===; reach for let only when you reassign.
  • [10, 9, 1].sort() gives [1, 10, 9] because it compares strings: pass (a, b) => a - b for numbers.
  • forEach doesn't wait for await: use for...of to go one by one, or await Promise.all(items.map(fn)) for parallel.
  • fetch only rejects on network errors: always check res.ok before reading the body.
  • Types vanish at runtime: validate API responses and JSON.parse results (for example with Zod) instead of trusting as.
  • Prefer unknown over any. Since TS 6, tsc file.ts stops with an error when a tsconfig.json is present: run plain npx tsc (or add --ignoreConfig).