javascript / expert
Snippet
Type-Safe Dependency Injection Tokens with Factory Providers
An `InjectionToken<T>` carries its type parameter all the way through `inject()`, so `useFeatureFlags()` returns a fully-typed `FeatureFlags` object with no casting anywhere in the chain. The `factory` option lets the token supply its own default when nothing else provides it, and because that factory itself calls `inject(RAW_CONFIG, { optional: true })`, the token can depend on another optional token without forcing every consumer to configure both. This pattern — a typed token whose factory composes other optional tokens — replaces the classic `@Optional() @Inject(TOKEN)` constructor boilerplate with a single declaration point that stays type-safe under strict mode.
snippet.js
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import { InjectionToken, inject } from '@angular/core';interface FeatureFlags {readonly darkMode: boolean;readonly betaCheckout: boolean;}const RAW_CONFIG = new InjectionToken<Partial<FeatureFlags>>('RAW_CONFIG');const FEATURE_FLAGS = new InjectionToken<FeatureFlags>('FEATURE_FLAGS', {providedIn: 'root',factory: () => {const raw = inject(RAW_CONFIG, { optional: true });return {darkMode: raw?.darkMode ?? false,betaCheckout: raw?.betaCheckout ?? false,};},});function useFeatureFlags(): FeatureFlags {return inject(FEATURE_FLAGS);}
angular
Breakdown
1
const FEATURE_FLAGS = new InjectionToken<FeatureFlags>('FEATURE_FLAGS', { ... })
The generic parameter binds the token's type to `FeatureFlags` for every future `inject(FEATURE_FLAGS)` call site.
2
factory: () => { const raw = inject(RAW_CONFIG, { optional: true }); ... }
Runs inside an injection context, so it can itself call `inject()` to compose values from other tokens rather than hardcoding defaults.
3
raw?.darkMode ?? false
Nullish coalescing supplies a concrete default only when `RAW_CONFIG` was never provided, keeping the returned object's fields non-optional.
4
function useFeatureFlags(): FeatureFlags { return inject(FEATURE_FLAGS); }
A typed injection wrapper usable in any injection context (constructors, field initializers, `provideAppInitializer`), returning `FeatureFlags` with no cast.