Past a certain level, writing better JavaScript is less about knowing more syntax and more about knowing which patterns keep a codebase understandable as it grows.

Discriminated Unions over Boolean Flags

A state object with isLoading, isError, and data allows impossible combinations. Model state as a union with a single tag and the impossible states disappear at the type level.

type State =
  | { status: "idle" }
  | { status: "loading" }
  | { status: "error"; error: Error }
  | { status: "success"; data: User[] };

Abort Everything

Every fetch tied to a component or user action should carry an AbortSignal. Stale responses overwriting fresh state is one of the most common production bugs in SPAs, and it's entirely preventable.

Structured Clone and Friends

Deep-copy hacks via JSON lose dates, maps, and cycles. structuredClone is built in, faster, and correct. Similarly, prefer Object.groupBy, Array.prototype.at, and native URLSearchParams over utility-library equivalents.

Measure Before Memoizing

Memoization has a cost: cache invalidation bugs and memory. Profile first. Most "slow" JavaScript is a few hot spots — a layout thrash, an accidental O(n²) — not a general lack of caching.