statelyai / xstate

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

Bug: When a state listens to more than one event, strict event type checking breaks #4951

Open rexsuit opened 2 weeks ago

rexsuit commented 2 weeks ago

Bug or feature request?

Bug with xstate v5.13.2

Description:

When creating a strictly typed machine with the setup function, and adding event definitions, TS informs if we try to listen to an undefined event.

image

However, this behavior breaks when we try to listen to more than one event on the same state

image

(Bug) Expected result:

I am able to listen to more than one event per state, and still have TS guarantee that I am used pre-defined events

(Bug) Actual result:

Listening to more than one event per state stops TS from informing me of my using undefined events

Link to reproduction or proof-of-concept:

Here's a codesandbox of both the machine where TS shows an where listens to an undefined event (and shows a TS error), and another machine the same sate listens to more than one event, and fails to inform the vscode user of the fact that an undefined error is being listened to.

Alternatively, here's a snipper that can be pasted into local dev. The snippet shoud cause a TS error if it listens to an event not defined in the "types" object, but does not as long as more than one "on" event is listened to.

export const testMachine = setup({
  types: {
    events: {} as { type: "start" },
  },
}).createMachine({
  initial: "Idle",
  states: {
    Idle: {
      on: {
        fakeEvent: "Pending",
        start: "Pending",
      },
    },
    Pending: {},
  },
});
davidkpiano commented 2 weeks ago

From my quick investigation, this has to do with EventDescriptor<TEvent> here: https://github.com/statelyai/xstate/blob/main/packages/core/src/types.ts#L577

Changing this to just TEvent['type'] solves the problem, although we still have to account for partial event descriptors.

cc. @Andarist