Reactivity in TypeScript/JavaScript - A Practical Guide
How to choose and implement a reactivity strategy for interactive TS/JS applications: games, web apps, simulations, and visualisations.
Who This Guide Is For
Software engineers making architectural decisions about how state changes propagate through a TypeScript/JavaScript application. The guide assumes familiarity with TypeScript and at least one front-end framework, but does not assume prior experience with any particular reactivity paradigm.
What This Guide Covers
Reactivity - the mechanism by which one part of a system responds to changes in another - is an architectural choice with far-reaching consequences for performance, correctness, testability, and maintainability. There is no single "best" approach. The right choice depends on your project's update model, scale, performance profile, and team expertise.
This guide covers three primary approaches and several variants:
| Approach | Core Mechanism | Section |
|---|---|---|
| Events (pub/sub) | Source emits; listeners subscribe | events.md |
| Signals (push-based observables) | Dependency graph auto-tracks reads; triggers on write | signals.md |
| Watchers (poll-based change detection) | Consumer polls a source each tick; compares to cached value | watchers.md |
A note on terminology: "watchers" is a pragmatic label for poll-based change detection, not a universally established paradigm name. Vue.js uses the same term for a similar (though push-based) concept; you may also see this approach called polling, dirty-checking, or pull-based observation. This guide uses "watchers" for brevity and because it describes the consumer's role: watching for changes on each tick.
Each section uses the same structure: concept, working code, benefits, drawbacks, and situational guidance.
Table of Contents
| Page | Key Topics |
|---|---|
| Push vs Pull Reactivity | Push model, pull model, hybrids, state-vs-change framing |
| Events (Pub/Sub) | EventTarget, typed emitters, subscription lifecycle, runtime traceability |
| Signals | Dependency tracking, effects, memos, batching, external integration |
| Watchers (Poll-Based) | Poll-based detection, watch, GC-safe lifecycle |
| Comparison & Decision Framework | Side-by-side summary, performance, correctness, testability, maintainability, decision flowchart |
| Worked Examples | Score display, ghost transitions, GSAP integration, asteroid field |
How to Read This Guide
- Start with the conceptual framing - Push vs Pull Reactivity introduces the taxonomy that underpins all three approaches.
- Read the approach(es) relevant to your project - each is self-contained with working examples.
- Use the comparison - Comparison & Decision Framework places all approaches side by side with a decision flowchart.
- Reference the worked examples - Examples shows each approach applied to the same scenarios across different project types.
┌──────────────────────────┐
│ Push vs Pull Framing │
│ (push-vs-pull.md) │
└────────────┬─────────────┘
│
┌─────────────────────┼─────────────────────┐
▼ ▼ ▼
┌────────────────┐ ┌────────────────┐ ┌────────────────┐
│ Events │ │ Signals │ │ Watchers │
│ (events.md) │ │ (signals.md) │ │ (watchers.md) │
└───────┬────────┘ └───────┬────────┘ └───────┬────────┘
│ │ │
└────────────────────┼────────────────────┘
▼
┌──────────────────────────┐
│ Comparison & Decision │
│ (comparison.md) │
└────────────┬─────────────┘
▼
┌──────────────────────────┐
│ Worked Examples │
│ (examples.md) │
└──────────────────────────┘Conventions Used
- Working code examples use TypeScript targeting the browser. Game examples use PixiJS for rendering and GSAP for tweening - both are widely used and framework-agnostic.
- Signal examples use SolidJS APIs as the reference implementation, with notes on Angular signals and the TC39 Signals proposal where they differ materially.
- All examples use classic arcade games (Pac-Man, Asteroids, Breakout, Space Invaders, Tetris) as domain references - they are widely familiar and map well to common interactive patterns.
Quick Orientation
If you already know what you're looking for:
- "I'm building a UI-driven web app with forms and data grids" → Signals are likely your best fit; see also Comparison § UI Apps.
- "I'm building a game or real-time simulation with a tick loop" → Watchers are worth serious consideration; see also Comparison § Tick-Based.
- "I'm building a loosely-coupled system with decoupled components" → Events may be the right foundation; see also Comparison § Decoupled Systems.
- "I need to decide between approaches for a new project" → Go straight to the Decision Framework.
This guide is a living document. Contributions, corrections, and additional worked examples are welcome.