assert-reducer-state.ts
edited
1function assertCurrentStep<S extends State['step']>(
2 state: State,
3 step: S,
4): asserts state is Extract<State, {step: S}> {
5 if (state.step !== step) {
6 throw new InvalidStateTransitionError(
7 `Invalid state transition: expecting ${step}, got ${state.step}`,
8 )
9 }
10}
11
12class InvalidStateTransitionError extends Error {
13 constructor(message: string) {
14 super(message)
15 this.name = 'InvalidStateTransitionError'
16 }
17}
18
19// For use in a reducer - means that you can ensure that
20// a transition between two states A and B can only take place
21// starting in state A, and provides typesafety
22// function reducer(state: State, action: Action): State {
23// switch (action.type) {
24// case 'GO_TO_STEP_2': {
25// assertCurrentStep(state, 'step 1')
26// return {
27// step: 'step 2',
28// ...action.payload,
29// }
30// }
31// }
32// }