ADR-0012: Type Testing Framework
- Status: accepted
- Date: 2025-11-04
Context
Canon lacked a lightweight way to express compile-time expectations. Contributors relied on intuition or ad-hoc type aliases to catch regressions. We needed a consistent, documented mechanism to assert relationships between types without introducing runtime overhead.
Decision
Introduce a dedicated type testing utility module that exports:
Expect<A, B>– resolves totruewhenAextendsB.IsTrue<A>– shorthand for positive assertions.IsFalse<A>– shorthand for negative assertions.invariant<T extends true>()– runtime no-op that fails compilation whenTis nottrue.
The helpers live in src/testing.ts and are re-exported from the package entry. Core type modules include representative invariants using these utilities for self-validation.
Consequences
Positive
- Compile-time guarantees become first-class and enforceable via
tsc --noEmit. - Documentation can reference a single, canonical pattern for invariants.
- Utilities are tree-shakeable because they erase at runtime.
Negative
- Developers must learn the new helpers and apply them consistently.
- Additional lint ordering rules now need to consider type-only specifiers.
Neutral
- No changes to runtime behaviour; existing APIs remain untouched aside from the new exports.
Related Decisions
- ADR-0011: Examples Documentation Generation from Source Files.