#>browser_ts_reference
browser internals TypeScript staff-level survey

Software Surface

Browser Fundamentals + TypeScript

Conceptual breadth at staff depth. Event loop priority, render pipeline cost, Web Platform APIs, the TypeScript type lattice, and advanced type patterns. SVG diagrams for memory; MDN and W3C links for precision.

~[event_loop]
single-threaded cooperative concurrency non-blocking I/O

JavaScript Event Loop

JS is single-threaded with a host-managed concurrency model. I/O and timers are offloaded to Web APIs; callbacks are enqueued when ready. The loop's priority ordering is what makes async code predictable.

JavaScript Event Loop — execution priority diagram Execution order: ① synchronous code on call stack; ② drain all microtasks (Promise.then, queueMicrotask, MutationObserver); ③ dequeue one macrotask (setTimeout, I/O, MessageChannel); ④ drain all microtasks again; ⑤ requestAnimationFrame callbacks before paint; ⑥ browser paints. Then repeat. ① sync call stack ② microtasks drain ALL ③ one task task queue ④ microtasks drain ALL ⑤ rAF → paint Promise .then/.catch queueMicrotask() MutationObserver cbs async/await desugars to .then setTimeout / setInterval MessageChannel I/O · UI events one task per loop tick requestAnimationFrame ResizeObserver cbs IntersectionObserver cbs if browser decides to paint Key: microtasks starve the loop if infinite — no paint until the µ-queue empties. MessageChannel beats setTimeout(0) for high-priority tasks.
µ queue

Microtask Queue

Drained completely after every task and after the initial script. No rAF or paint occurs until the microtask queue is empty. Starvation risk: a microtask that enqueues itself loops forever, blocking all I/O and rendering.

  • Promise.then
  • queueMicrotask
  • MutationObserver
  • async/await
task queue

Task Queue (Macrotasks)

One task dequeued per loop iteration. Multiple distinct task sources exist (timer, I/O, UI events); the UA may interleave them. MessageChannel yields a macrotask without the 4 ms minimum clamp of setTimeout.

  • setTimeout
  • setInterval
  • MessageChannel
  • I/O callbacks
rAF

requestAnimationFrame

Fires immediately before the browser paints — ideal for all visual mutations. Batched per frame (~16 ms at 60 fps). Pauses when the tab is hidden. Use to batch DOM reads before writes and avoid layout thrashing.

  • requestAnimationFrame
  • requestIdleCallback
  • frame budget
scheduler

Scheduler API

scheduler.postTask() gives explicit priority control: user-blocking, user-visible, background. scheduler.yield() cooperatively yields a long task back to the event loop without relinquishing priority.

  • scheduler.postTask
  • scheduler.yield
  • TaskController
  • Long Tasks API
*[render_pipeline]
layout paint composite CRP

Browser Render Pipeline

Which pipeline stages a CSS property triggers determines its cost. Properties like transform and opacity on composited layers skip layout and paint entirely — the GPU reassembles pre-rasterized layers. Properties like width invalidate all stages.

Browser Render Pipeline Stages: HTML + CSS are parsed into DOM and CSSOM; merged into the Render Tree; Layout computes geometry (reflow); Paint rasterizes pixels per layer; Composite assembles layers on the GPU and outputs to screen. transform/opacity trigger composite only (cheap fast path). width/height/top trigger layout + paint + composite (expensive). HTML + CSS DOM CSSOM Render Tree excludes display:none Layout (reflow) Paint (rasterize) Composite (GPU layers) Screen transform / opacity → composite only (fast path) width / top / font-size → layout + paint + composite (expensive) Forced sync layout: reading offsetWidth after a write flushes the pipeline. Batch reads before writes in rAF.
DOM

Document Object Model

Live tree of nodes. Script mutations trigger style recalc. documentFragment batches insertions off-tree. TreeWalker traverses efficiently. Range works across arbitrary node boundaries. MutationObserver callbacks fire as microtasks.

  • Node
  • Element
  • DocumentFragment
  • TreeWalker
  • Range
  • MutationObserver
CSSOM

CSSOM + Cascade

Style resolution order: origin → cascade layers → specificity → source order. getComputedStyle returns resolved values (forces style flush). @layer adds an explicit origin tier. @property enables typed custom properties with registered syntax.

  • @layer
  • specificity
  • @property
  • :is() :where()
  • custom properties
layout

Layout (Reflow)

Computes box geometry. Reading layout properties (offsetWidth, getBoundingClientRect) after mutations forces a synchronous reflow. contain: layout limits reflow scope. ResizeObserver fires before paint after each reflow.

  • contain: layout
  • will-change
  • ResizeObserver
  • intrinsic sizing
composite

Compositing Layers

transform, opacity, and filter on a promoted layer skip layout and paint — the GPU reassembles pre-rasterized bitmaps. will-change: transform promotes eagerly (memory cost). content-visibility: auto skips layout/paint for off-screen content.

  • will-change
  • GPU layer
  • content-visibility
  • isolation: isolate
@[web_platform]
network observers workers storage modules

Web Platform APIs

~[fetch]

Fetch API + Streams

Promise-based network I/O. Response.body is a ReadableStream enabling progressive processing. AbortController cancels in-flight requests. Request/Response are structured-cloneable and composable in Service Workers.

  • AbortController
  • ReadableStream
  • TransformStream
  • WritableStream
  • Response.body
?[observe]

Observer APIs

Four observer types: IntersectionObserver (viewport crossing), MutationObserver (DOM changes — microtask delivery), ResizeObserver (element size changes — before paint), PerformanceObserver (metric entries). All avoid polling.

  • IntersectionObserver
  • MutationObserver
  • ResizeObserver
  • PerformanceObserver
*[worker]

Web Workers

True OS-thread parallelism; workers cannot access the DOM. Communication via postMessage (structured clone) or Transferable (zero-copy). SharedWorker shared across browsing contexts. SharedArrayBuffer + Atomics enable wait-free shared memory.

  • postMessage
  • Transferable
  • SharedArrayBuffer
  • Atomics
  • SharedWorker
![sw]

Service Workers

Network proxy off the main thread. Lifecycle: installactivatefetch interception. skipWaiting() + clients.claim() for immediate takeover. Cache API stores Request/Response pairs. Enables offline-first and background sync.

  • Cache API
  • Background Sync
  • Push API
  • skipWaiting
  • clients.claim
$[storage]

Storage APIs

localStorage / sessionStorage: synchronous, string-only, ~5 MB. IndexedDB: async, structured data, large capacity, transactions, indices, available in workers. StorageManager.estimate() queries available quota. Cache API keyed on Request objects.

  • IndexedDB
  • localStorage
  • StorageManager
  • Cache API
  • Cookie Store API
~[ws]

WebSocket + SSE

WebSocket: full-duplex binary-capable TCP channel. EventSource: server-push over HTTP, text-only, auto-reconnect, simpler auth model. Use SSE when only server→client streaming is needed; WS for bidirectional. WebTransport over QUIC is the emerging successor.

  • WebSocket
  • EventSource
  • WebTransport
  • binary frames
%[perf]

Performance APIs

Core Web Vitals: LCP (Largest Contentful Paint), INP (Interaction to Next Paint, replaces FID), CLS (Cumulative Layout Shift). performance.mark / measure for custom spans. PerformanceObserver streams entries asynchronously.

  • LCP
  • INP
  • CLS
  • TTFB
  • Long Tasks
  • User Timing
#[esm]

ES Modules + Import

type="module" scripts defer by default, run in strict mode, and have lexical scope. import() dynamic import returns a Promise. import.meta.url is the module's own URL. importmap remaps bare specifiers to URLs at HTML level. Module map prevents double-evaluation.

  • import.meta
  • dynamic import()
  • importmap
  • modulepreload
![browser_security]
SOP CORS CSP SameSite SRI

Browser Security Model

Browser Security Model — concentric layers Security layers from innermost to outermost: Execution context at center. Same-Origin Policy (origin = scheme + host + port). CORS headers for cross-origin resource access. Content-Security-Policy allowlisting resource origins. HTTPS/TLS at the outermost transport layer. HTTPS / TLS Content-Security-Policy CORS headers Same-Origin Policy execution context origin = scheme + host + port · SameSite controls cookie dispatch · SRI validates subresource integrity
=[origin]

Same-Origin Policy

Origin = scheme + host + port. Scripts from origin A cannot read responses or DOM of origin B. Applies to fetch, XHR, window.opener, iframe content access, Web Storage, and cookies. The invariant all other mechanisms build on.

  • origin
  • site
  • schemelessly same-site
  • opaque origin
@[cors]

CORS

Credentialed or non-simple requests trigger a preflight (OPTIONS). Key headers: Access-Control-Allow-Origin, ACAO-Credentials. Credentials require non-wildcard ACAO. COEP/COOP/CORP enable SharedArrayBuffer and cross-origin isolation.

  • preflight
  • ACAO
  • credentials
  • COEP
  • COOP
  • CORP
![csp]

Content Security Policy

Allowlist for script, style, connect, img, media, and other resource sources. script-src 'nonce-{x}' is best practice for inline scripts. strict-dynamic propagates trust to dynamically-created scripts. Report-only mode enables incremental rollout via Reporting API.

  • nonce
  • strict-dynamic
  • report-to
  • Trusted Types
$[cookies]

Cookies + SameSite

SameSite=Strict: no cross-site dispatch. Lax: top-level navigations only (default since Chrome 80). None requires Secure. HttpOnly prevents JS access. The __Host- prefix requires Secure, no Domain attribute, and path=/. CHIPS partitions third-party cookies by top-level site.

  • SameSite
  • HttpOnly
  • __Host-
  • CHIPS
  • partitioned
$[ts_type_system]
structural typing type lattice inference narrowing

TypeScript Type System

TypeScript uses structural (duck) typing — compatibility is determined by shape, not identity. The type system forms a lattice: unknown is the top type (all values are assignable to it); never is the bottom type (no value inhabits it). any escapes the lattice entirely.

TypeScript Type Lattice Type hierarchy: unknown at top (all types assignable to it). Below: primitive types (string, number, boolean, symbol, bigint, object). Below primitives: literal types (string literals, numeric literals, true/false). never at bottom (assignable to everything, inhabited by nothing). any shown separately as a bypass that escapes the lattice bidirectionally. Arrows point from supertype to subtype (assignment direction). unknown top type — require narrowing before use string number boolean bigint object symbol undef | null "hello"… 0|1|42… true|false ← literal types are subtypes of their primitive never bottom type — assignable to everything, inhabited by nothing any ⚠ lattice bypass
unknown vs any

unknown — safe top type

unknown requires narrowing before use (type-safe). any escapes the type system entirely — bidirectional assignability. Prefer unknown for external data (JSON, API responses, user input). noImplicitAny bans accidental widening to any.

  • unknown
  • any
  • noImplicitAny
  • type assertion
never

never — bottom type

Inhabited by nothing. Appears at exhaustive checks (all union members handled), in return types of functions that always throw, and as the intersection of contradictory types (string & number). never is assignable to every type — use it to detect missing branches.

  • exhaustive check
  • assertion function
  • unreachable code
structural

Structural Typing

Compatibility is shape-based: T is assignable to U if T has at least all required properties of U with compatible types. Excess property checking applies only at fresh object literal assignment, not at variable assignment — a common source of confusion.

  • excess property check
  • freshness
  • index signatures
  • covariance
  • contravariance
is / asserts

Type Narrowing

Built-in: typeof, instanceof, in, truthiness, equality. User-defined: x is T type predicate returns a boolean; asserts x is T asserts or throws. Discriminated unions: a shared literal property identifies each variant — TS narrows based on the literal.

  • type predicate
  • discriminated union
  • control flow analysis
  • asserts
Utility<T>

Utility Types

Standard type transforms: Partial, Required, Readonly, Pick<T,K>, Omit<T,K>, Record<K,V>, Exclude, Extract, NonNullable, ReturnType<F>, InstanceType<C>, Awaited<T>, NoInfer<T>.

  • Partial
  • Omit
  • ReturnType
  • Awaited
  • NoInfer
satisfies

satisfies + as const

satisfies T checks a value against a type without widening the inferred type. as const produces readonly literal types. Combined: const p = {...} as const satisfies Record<...> — constraint checking with precise inference preserved. Available since TypeScript 4.9.

  • satisfies
  • as const
  • const type parameters
  • const assertions
^[ts_advanced]
generics conditional types mapped types template literals declaration merging

TypeScript Advanced Patterns

T extends U

Generics + Inference

Constraints: T extends K restricts T to subtypes of K. Inference sites: TS infers from call sites, conditional clauses, infer. NoInfer<T> blocks inference at a site without removing the constraint. Variance: function params are contravariant; return types covariant.

  • constraints
  • infer
  • NoInfer
  • variance
  • covariance
  • const type param
T extends U ? X : Y

Conditional Types

infer R captures a type within a conditional branch. Distributivity: over a naked union type parameter, the conditional distributes member-by-member. To prevent distribution, wrap in a tuple: [T] extends [U]. Basis for ReturnType, Awaited, Parameters.

  • infer
  • distributive
  • [T] extends [U]
  • deferred
{ [K in T]: … }

Mapped Types

Iterate over a union of keys. Modifiers: +readonly, -readonly, +?, -?. Key remapping with as: [K in keyof T as Capitalize<string & K>]. Filter keys by returning never from the as clause. Homomorphic mapped types preserve optionality and readonly.

  • keyof
  • in keyof
  • as clause
  • modifiers
  • homomorphic
`${A}${B}`

Template Literal Types

Construct string types from literal unions. Combine with mapped types to derive event names, accessor keys, CSS property strings. Built-in string intrinsics: Uppercase, Lowercase, Capitalize, Uncapitalize. infer inside template literals matches string patterns.

  • Capitalize
  • template literal infer
  • string union
  • intrinsic string types
declare module

Declaration Merging

Interfaces merge across declarations; type aliases do not. Module augmentation: declare module 'x' { ... } extends an existing module's types. Global augmentation: declare global { ... }. Commonly used for Express Request, Jest matchers, Vite ImportMeta, and environment variables.

  • interface merging
  • module augmentation
  • ambient declaration
  • declare global
tsconfig

tsconfig + Project References

Key flags: strict enables noImplicitAny + strictNullChecks + more. moduleResolution: "bundler" for Vite/esbuild. verbatimModuleSyntax enforces explicit type-only imports. Project references (composite: true + references) enable incremental builds and type-check boundaries across monorepo packages.

  • strict
  • composite
  • references
  • verbatimModuleSyntax
  • isolatedModules