ADR-011 — TypeScript throughout
Status · Accepted Date · 2026-04-28 Supersedes · ADR-002 (vanilla JS) TA anchor · §stack
Context
ADR-002 chose vanilla JS on the basis that the rendering surfaces are imperative and a framework adds abstraction without benefit. That reasoning holds for the physics and rendering code. It does not hold for the application as a whole: stateful HUD panels, reactive telemetry values, multi-tab detail panels, dynamic card grids, and a data layer with complex JSON shapes are all harder to maintain and debug in untyped JavaScript at production scale. The orbital math library especially — keplerPos, visViva, auToPx — benefits directly from type-checked function signatures that catch unit errors at compile time.
Decision
TypeScript throughout. All source files in src/ are .ts or .svelte (which supports TypeScript natively). The orbital library, data client, router, and all screen modules are typed. JSON data shapes are typed via interfaces in src/types/.
Rationale
At the scale of millions of users and multiple contributors, untyped JavaScript becomes archaeology. TypeScript catches whole classes of bugs — wrong argument order in keplerPos, passing a string where a number is expected, accessing a field that doesn't exist on a mission record — at compile time rather than at runtime in a user's browser. The cost is marginal: Vite and SvelteKit both support TypeScript natively with zero additional configuration.
Alternatives considered
- Vanilla JS with JSDoc types — provides IDE hints but no compile-time checking; fails silently in CI; rejected.
- Flow — less ecosystem support than TypeScript; no SvelteKit integration; rejected.
Consequences
Positive: compile-time error catching; self-documenting function signatures; contributor onboarding is faster when types describe data shapes explicitly. Negative: slightly more verbose; contributors must know TypeScript (low bar — it's a superset of JS).
Implementation notes
tsconfig.json at repo root. strict: true. All new files .ts. Existing prototype code ported during screen extraction in Slices 3–5.