Skip to content

Commit 22c22ed

Browse files
feat(overmind): statemachines receives the typed state on entry and exit
1 parent 2d486f2 commit 22c22ed

File tree

2 files changed

+52
-4
lines changed

2 files changed

+52
-4
lines changed

packages/node_modules/overmind/src/statemachine.test.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,4 +231,51 @@ describe('Statemachine', () => {
231231
overmind.state.reset()
232232
expect(overmind.state.state).toBe('FOO')
233233
})
234+
235+
test('should pass statemachine to transition callback, correctly typed', () => {
236+
expect.assertions(3)
237+
238+
type States = {
239+
state: 'FOO'
240+
foo: string
241+
} | {
242+
state: 'BAR'
243+
bar: string
244+
}
245+
246+
const state = statemachine<States>({
247+
FOO: ['BAR'],
248+
BAR: ['FOO']
249+
}, {
250+
state: 'FOO',
251+
foo: 'bar'
252+
})
253+
254+
const transition: Action = ({ state }) => {
255+
state.BAR(() => {
256+
state.FOO((current) => {
257+
current.foo = 'bar2'
258+
})
259+
}, (current) => {
260+
current.bar = 'baz2'
261+
})
262+
}
263+
264+
const config = {
265+
state,
266+
actions: {
267+
transition
268+
}
269+
}
270+
271+
interface Action extends IAction<typeof config, void, void> {}
272+
273+
const overmind = createOvermind(config)
274+
overmind.actions.transition()
275+
expect(overmind.state.state).toBe('FOO')
276+
// @ts-ignore
277+
expect(overmind.state.foo).toBe('bar2')
278+
// @ts-ignore
279+
expect(overmind.state.bar).toBe('baz2')
280+
})
234281
})

packages/node_modules/overmind/src/statemachine.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { IState } from '.'
21
import { PROXY_TREE, VALUE } from 'proxy-state-tree'
32

3+
import { IState } from '.'
4+
45
type TStates = IState & {
56
state: string | number,
67
}
@@ -13,7 +14,7 @@ export type Statemachine<States extends TStates> = States & {
1314
reset: () => void
1415
whenTransitioned: (state: States["state"]) => Promise<void>
1516
} & {
16-
[State in States["state"]]: <T extends () => any>(entry?: T, exit?: () => void) => T extends () => infer U ? U : void
17+
[State in States["state"]]: <O>(entry?: (current: States extends { state: State } ? States : never) => O, exit?: (current: States extends { state: State } ? States : never) => void) => O
1718
}
1819

1920
const CURRENT_EXIT = Symbol('CURRENT_EXIT')
@@ -35,10 +36,10 @@ class StateMachine<States extends TStates> {
3536
const tree = (this[PROXY_TREE].master.mutationTree || this[PROXY_TREE])
3637

3738
tree.enableMutations()
38-
if (this[CURRENT_EXIT]) this[CURRENT_EXIT]()
39+
if (this[CURRENT_EXIT]) this[CURRENT_EXIT](this)
3940
this[VALUE][CURRENT_EXIT] = exit
4041
this.state = key as any
41-
const result = entry && entry()
42+
const result = entry && entry(this)
4243
tree.blockMutations()
4344

4445
if (this[VALUE][PENDING_TRANSITIONS][this.state]) {

0 commit comments

Comments
 (0)