Typed Keys and Providers
Inject values and interfaces (not just classes) with TypedInjectionKey and @Provider.
Classes inject by their own type. Everything else — configuration values, interfaces with swappable implementations, computed objects — injects through a typed key plus a provider.
Define a typed key
By convention, keys live as static members of an *Injections class:
The generic (<string>) is the contract: lint verifies that whatever a provider returns for this key, and whatever type a consumer declares for it, both match. Bare string or symbol tokens are rejected by design — every token carries a static type.
Use the same key instance at registration and injection (import it; don't construct a second copy) — token identity is reference-based.
Provide a value
A provider is a method decorated with @Provider(key), hosted on a class listed in services:
Provider hosts go in the same services list as everything else — that's how the worker knows they exist.
Consume it
Declare the parameter as anything other than string and lint objects — the key's generic is enforced at both ends.
Patterns
- Interface + implementation: define
TypedInjectionKey<PaymentGateway>, provide the concrete class, and consumers depend only on the interface. Swap implementations in one place (tests included). - Caching:
@Provider(key, { factoryType: 'caching' })memoizes the factory result instead of re-running it per resolution. - System keys: the framework exposes its own typed keys: notably
BaseInjections.DeferredActions, the per-request deferred executor for scheduling post-response work (also reachable ascontext.deferred— see Use the RequestContext).