Improve the type definition for `state` and `invoke` functions
The first thing I did when I started evaluating this library was try to set up a situation with multiple transitions out of a single state, but I found that my simple test did not typecheck
```ts
const machine = createMachine({
one: state(transition('go-two', 'two'), transition('go-three', 'three')), // TS2345: Argument of type Transition<"go-three"> is not assignable to parameter of type Transition<"go-two">
two: state(transition('go-one', 'one')),
three: state()
});
```
`state` accepts multiple transitions, each of which can have its own type. However, the typescript type was only extracting the type of the first argument. I updated the type of `state` to extract the type of each of its arguments, and union them together, which allows the previous snippet to compile.
Then, playing with nested states, it appears that the example from the readme doesn't typecheck either
```ts
const stopwalk = createMachine({
walk: state(
transition('toggle', 'dontWalk'),
),
dontWalk: state()
});
const stoplight = createMachine({
green: state(
transition('next', 'yellow')
),
yellow: state(
transition('next', 'red')
),
red: invoke(stopwalk,
transition('done', 'green')
)
});
const s = interpret(stoplight, console.log);
s.send("next")
s.send("next")
s.child?.send("toggle") // TS2345: Argument of type "toggle" is not assignable to parameter of type <...>
```
So, update the `invoke` function's type to propagate the transitions from a child state machine. This is not really 100% correct, as it means that the child's transitions are now available on the parent (from typescript's perspective, it's more permissive than it should be), but at least it typechecks. Properly typing this project would be a bigger task, and I don't have much more time to spend on it, but thought I'd share my progress.
合并状态:未合并 关闭于 2025-12-10 2 条评论