statelyai / xstate

Actor-based state management & orchestration for complex app logic.
https://stately.ai/docs
MIT License
26.98k stars 1.24k forks source link

Bug: [TypeScript] Unknown action when using `enqueue()` and referencing an action defined with `enqueueActions` #4820

Open offirgolan opened 6 months ago

offirgolan commented 6 months ago

XState version

XState version 5

Description

Typescript errors when calling an action via enqueue when the action being called is defined with enqueueActions.

setup({
  actions: {
    foo: enqueueActions(({ enqueue }) => {
      enqueue({ type: "bar" }); // TS ERROR
    }),
    bar: enqueueActions(({ enqueue }) => {
      enqueue.raise({ type: "submit" });
    }),
  },
})

Expected result

Typescript should not error when calling enqueue({ type: "bar" });

Actual result

Object literal may only specify known properties, and 'type' does not exist in type

Reproduction

https://codesandbox.io/p/devbox/currying-darkness-nvv5vh

Additional context

No response

Andarist commented 6 months ago

This is a current limitation that we are facing. TS can't infer this situation correctly: TS playground

boneskull commented 6 months ago

Can a type assertion be used as a workaround? I'm not sure what it'd be.

offirgolan commented 6 months ago

@Andarist I found another TS error: TS Playground

setup({
  actions: {
    bar: enqueueActions(({ check }) => {
      check(stateIn('a'));
    }),
  },
}).createMachine({
  states: {
    a: {},
    b: {}
  }
});

+1 to @boneskull, if there is a TS limitation are there utility types that can be exposed to help mitigate the issue via type assertions?

offirgolan commented 6 months ago

FWIW Using createMachine with the deprecated second argument instead of setup and defining types.actions and types.guards works.

Because of these TS limitations in setup, should I switch back to using createMachine?

Edit:

Another alternative is to add types.actions and types.guards to setup.

andrecrimb commented 4 months ago

Any updates?

davidkpiano commented 4 months ago

For now, just // @ts-ignore this - the action will work, we're just running into a TypeScript limitation, as previously mentioned.

with-heart commented 4 months ago

For now, just // @ts-ignore this

// @ts-expect-error so it'll become an error when (if?) the types work correctly 😁

UberMouse commented 2 months ago

Just a comment that attempting to suppress the error with // @ts-expect-error did not work for me, because it breaks the Snapshot matches function. The possible states resolve to never. As soon as I moved the enqueueActions from my setup to be an inline action the states started resolving properly again.