Skip to content

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:

ApproachCore MechanismSection
Events (pub/sub)Source emits; listeners subscribeevents.md
Signals (push-based observables)Dependency graph auto-tracks reads; triggers on writesignals.md
Watchers (poll-based change detection)Consumer polls a source each tick; compares to cached valuewatchers.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

PageKey Topics
Push vs Pull ReactivityPush model, pull model, hybrids, state-vs-change framing
Events (Pub/Sub)EventTarget, typed emitters, subscription lifecycle, runtime traceability
SignalsDependency tracking, effects, memos, batching, external integration
Watchers (Poll-Based)Poll-based detection, watch, GC-safe lifecycle
Comparison & Decision FrameworkSide-by-side summary, performance, correctness, testability, maintainability, decision flowchart
Worked ExamplesScore display, ghost transitions, GSAP integration, asteroid field

How to Read This Guide

  1. Start with the conceptual framing - Push vs Pull Reactivity introduces the taxonomy that underpins all three approaches.
  2. Read the approach(es) relevant to your project - each is self-contained with working examples.
  3. Use the comparison - Comparison & Decision Framework places all approaches side by side with a decision flowchart.
  4. 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:


This guide is a living document. Contributions, corrections, and additional worked examples are welcome.