mattpocock / xstate-codegen

A codegen tool for 100% TS type-safety in XState
MIT License
245 stars 12 forks source link

Invoked callbacks are not strict with the events that can be dispatched to the machine #19

Closed rjdestigter closed 4 years ago

rjdestigter commented 4 years ago

Example configuration:

...
states: {
    idle: {
      invoke: {
        src: () => callback => {}
      },
      on: {
        START: "running"
      },
    },
    running: {},
}
...

callback will be inferred to be of type Sender rather than only accepting events with event type "START".

mattpocock commented 4 years ago
export declare type InvokeCallback = (callback: Sender<any>, onReceive: Receiver<EventObject>) => any;

This is tricky, because the type InvokeCallback in XState is not currently generic, meaning that Sender cannot yet be made generic without overriding the type our side. This is fine, but we should also make the type in XState generic too.

It also appears you can receive events to the invoked actor. Which events should be allowed to occur?

Also, I think we should probably allow any events to be sent by an invoked actor, because this invoke could occur at a top-level, or as part of two parallel states. I don't use this API much though so I might be confused. Could you elaborate more on what you'd need from this API?

mattpocock commented 4 years ago

cc @davidkpiano

davidkpiano commented 4 years ago

We can probably tighten up the types here to make it only able to "send back" events of type TEvent of the parent, but yes it should be able to receive any event (what a machine can send is not the same as what it can receive).

mattpocock commented 4 years ago

Can the receiver receive any type of event, or only those permitted by the machine? Wondering if it needs to include two generics, one for the sender and one for the receiver.

davidkpiano commented 4 years ago

Ideally it should be able to specify what types of events it can receive, and this should be owned by that "callback actor" itself and not the parent machine. For now we can assume that it can receive any event.

mattpocock commented 4 years ago

OK, do you mean that the current Sender<any> implementation is as good as XState v4 can handle? That likely means we can close this.

davidkpiano commented 4 years ago

Yes, this can be closed. The original example by @rjdestigter has a counter-example:

states: {
    idle: {
      invoke: {
        id: 'invoked',
        src: () => callback => {}
      },
      on: {
        START: "running",
        OTHER: {
          // any event can be sent
          actions: send('ANY_EVENT', { to: 'invoked' }
        }
      },
    },
    running: {},
}