JavaScript / TypeScript
Re-sharpen the JS/TS details that atrophy first: coercion, closures, this, the event loop, and a type system you drive instead of fight.
71 concepts426 live tasks
Start practicing freeWhat's inside
Language Core & Coercion
var hoists to undefined; let and const hoist into the TDZ
== follows an algorithm, not vibes
ToPrimitive: valueOf, toString, and Symbol.toPrimitive
+ is the only operator that concatenates
Three equality algorithms: ===, SameValueZero, Object.is
?? only skips null/undefined; || skips every falsy
Every number is a float64, until it can't be
Functions, Scope & Closures
Function declarations hoist whole; expressions don't
Closures capture variables, not values
let creates a fresh binding per loop iteration; var doesn't
Arrows have no this, arguments, new.target, or prototype
Default parameters evaluate lazily, in their own scope
Partial application is just a closure factory
Closures can retain more memory than they use
this, Prototypes & Classes
this is decided at the call site, by four rules
Extracting a method detaches its this
Arrow this is resolved like a variable lookup
Property reads walk the chain; writes don't
What new actually does (and when return hijacks it)
Class fields live per-instance; methods live on the prototype
#private is real privacy, not a convention
Property descriptors: the machinery under every object
The Event Loop & Async
One thread, a task queue, and a run-to-completion contract
The microtask queue drains completely between tasks
Every .then returns a new promise; the callback's return decides its fate
await suspends the function, not the thread
try/catch works across await, with sharp edges
A promise nobody awaits fails silently, until it doesn't
all, allSettled, race, any: four failure semantics
Awaiting in a loop serializes; start first, await after
Iterators, Generators & Collections
Symbol.iterator is the contract behind for-of and spread
Generators are pausable functions that produce iterators
next(v), throw(e), return(v): callers talk back to generators
for await consumes streams one settled value at a time
Map is for dynamic keys; objects are for records
WeakMap keys don't keep their objects alive
WeakRef and FinalizationRegistry: GC as an observable, barely
Spread copies one level; structuredClone goes deep
Modules & Tooling Realities
ESM exports are live bindings; CJS exports are a snapshot object
The interop layer: default imports, __esModule, and the dual-package hazard
Circular imports don't error; they hand you incomplete modules
import() is the code-splitting seam
Tree-shaking is dead-code elimination gated on purity
package.json exports: the map that decides what importers see
Top-level await makes module loading asynchronous for everyone upstream
Declaration merging: how libraries let you extend their types
TypeScript Type System Fundamentals
TypeScript compares shapes, not names
Literals widen unless something anchors them
interface vs type: fewer differences than the arguments about them
Narrowing is control-flow analysis over your ifs
unknown is the honest any
Discriminated unions make illegal states unrepresentable
Fresh object literals get stricter checking, deliberately
satisfies: validate against a type without widening to it
Partial, Pick, Omit, ReturnType: derive types, don't duplicate them
Advanced Types & Generics
Generics preserve the relationship between input and output
Where the compiler infers T from, and why it sometimes picks wrong
keyof and T[K]: types that index like values do
Conditional types are if-statements evaluated by the compiler
infer: destructuring for types
Conditionals distribute over naked union parameters
Mapped types: iterate over keys, transform, even rename
Template literal types: string manipulation in the type system
Variance: why Array<Dog> isn't safely an Array<Animal>
Runtime Edge Cases & Performance
Hidden classes: why property order and shape stability matter
Packed vs holey, SMI vs double: arrays have internal kinds
GC collects the unreachable: leaks are unintended reachability
JSON.stringify drops, mangles, and throws by spec
Proxy traps object operations; Reflect forwards them correctly
Microtasks can starve rendering and I/O
Catastrophic backtracking: the regex that takes down the service
From the blog
- The skills that decay first when AI writes your code
Recall decays faster than recognition, which is why reviewing AI-written code feels like understanding. The skills that slip first and a ten-minute self test.
- Best daily coding practice apps for working developers
Compare daily coding practice apps for working developers, from interview prep and courses to short recall sessions that keep familiar engineering skills fresh.
- Reviewing code you could not have written
How senior engineers can review AI-generated code for both correctness and comprehension, spot hidden risks, and protect trust in their technical judgment at work.

