javascript / expert
Snippet
Exhaustive Union Narrowing for Reactive Form States
Uses a discriminated union to model every reachable state of a form submission lifecycle, then leans on TypeScript's control-flow narrowing inside a switch statement to make each branch's extra fields (recordId, message, retryable) available without casting. The assertNever helper turns an unhandled case into both a compile-time error, if a new state variant is added later, and a runtime guard.
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
24
type FormState =| { status: 'idle' }| { status: 'submitting' }| { status: 'success'; recordId: string }| { status: 'error'; message: string; retryable: boolean };function assertNever(value: never): never {throw new Error(`Unhandled form state: ${JSON.stringify(value)}`);}function describeState(state: FormState): string {switch (state.status) {case 'idle':return 'Ready to submit';case 'submitting':return 'Submitting…';case 'success':return `Saved as ${state.recordId}`;case 'error':return state.retryable ? `Retry: ${state.message}` : `Failed: ${state.message}`;default:return assertNever(state);}}
angular
Breakdown
1
function assertNever(value: never): never
Accepts only the `never` type, so if a new FormState variant is added without a matching case, TypeScript flags the call site as a type error at the default branch.
2
case 'error':\n return state.retryable ? ... : ...;
Within this case, TypeScript narrows `state` to the error variant specifically, so `retryable` and `message` are accessible without optional chaining.
3
default:\n return assertNever(state);
The exhaustiveness check — reachable only if a status value slips through that no case handles, at which point it throws with the offending payload.