intermediate · 20 minute study
Follow the compiler through a branch
Narrowing lets one function safely handle success, pending and failure without optional-property guesswork.
Useful preparation · 1 prerequisite
Use this as a map, not a lock. If these ideas are familiar, continue.
- A type is a promise; a boundary needs evidence — An API, a save file and a restored backup can all disagree with your local types. Learn to turn uncertainty into a checked domain value.
First, build a mental model
A union is a set of possible shapes. A discriminant is an observation that shrinks that set. At each branch the compiler asks which members can still exist.
- Use one literal field shared by every union member.
- Read member-specific data only after checking its discriminator.
- A never assignment can expose a missing case when the union grows.
- Changing shared mutable data can invalidate your human assumptions; prefer stable local values.
type Save =
| { status: 'idle' }
| { status: 'saved'; revision: number }
| { status: 'failed'; message: string };
function label(save: Save): string {
switch (save.status) {
case 'idle': return 'Ready';
case 'saved': return `Revision ${save.revision}`;
case 'failed': return save.message;
default: { const impossible: never = save; return impossible; }
}
}- Before switch
save is idle OR saved OR failed.
- Saved branch
status='saved' implies revision exists; message does not.
- Default
No known member remains, so save is never.
Production thinking
Take this beyond the example.
Model loading/error/success and business transitions explicitly. Avoid asserting away the error that reveals a missing state.
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 · Compatible shapes, excess properties and shallow readonly →