0 day streak
javascript / expert
Snippet

Type-Safe State Machines with useReducer and Discriminated Unions

Using TypeScript discriminated unions with React's useReducer creates a formal state machine. This pattern ensures that only valid state transitions are possible and eliminates 'impossible states' (like having both data and an error simultaneously).

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
25
type State =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: string[] }
| { status: 'error'; error: Error };
type Action =
| { type: 'FETCH' }
| { type: 'RESOLVE'; payload: string[] }
| { type: 'REJECT'; error: Error };
const reducer = (state: State, action: Action): State => {
switch (state.status) {
case 'idle':
return action.type === 'FETCH' ? { status: 'loading' } : state;
case 'loading':
return action.type === 'RESOLVE'
? { status: 'success', data: action.payload }
: action.type === 'REJECT'
? { status: 'error', error: action.error }
: state;
default:
return state;
}
};
react
Breakdown
1
type State = ...
Defines mutually exclusive states to prevent illegal property combinations.
2
switch (state.status)
Leverages TypeScript's exhaustive checking to ensure all states are handled correctly during transitions.