advanced · 23 minute study
Keep useful literals without making false assertions
Route names, event names and configuration keys are small languages. Preserve their exact vocabulary so typos become useful compiler errors.
Useful preparation · 1 prerequisite
Use this as a map, not a lock. If these ideas are familiar, continue.
- Conditional types are type-level decisions — Read utility types intelligently and know when distributive behavior creates a surprising union.
First, build a mental model
Inference chooses a type broad enough for the intended use. `as const` preserves literals and readonly properties; `satisfies` checks compatibility while retaining the expression's useful inferred detail.
- A mutable string property often widens to string.
- as const keeps literal information; it does not freeze runtime objects.
- satisfies checks a contract without replacing the expression with the broad target type.
- Template literal types construct finite vocabularies from unions.
type EventName = `${'player' | 'order'}:${'created' | 'updated'}`;
const route = { method: 'GET', path: '/orders' } as const;
const limits = { small: 10, large: 50 } satisfies Record<string, number>;
type LimitName = keyof typeof limits;
const event: EventName = 'player:updated';
const selected: LimitName = 'small';- Literal
route.method is the literal GET, not every string.
- Shape check
limits must contain numeric values; its known keys remain small | large.
- Vocabulary
EventName permits four combinations.
Production thinking
Take this beyond the example.
Keep route/config/event vocabularies finite where the domain is finite. Avoid giant template combinations that add compile cost without useful protection.
Sources and further reading
Your evidence
unseen is a local learning signal, not a credential or proof of production competence.
Explain the mental model, then explicitly acknowledge it. Opening a page is not evidence.
Supported retries can complete this lesson. Independent evidence and delayed review determine the skill stage.
Next lesson · A callback must accept everything its caller can send →