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: supplying generic input argument to setup actors for stubbing breaks invoke type inference #4855

Open sourcec0de opened 5 months ago

sourcec0de commented 5 months ago

XState version

XState version 5

Description

Hello :wave:

Running into a really odd typing problem when trying to create typed generic actor stubs and attempting to invoke them using src

The error I'm seeing is invoke

is not assignable to type 'undefined'

This only seems to happen when providing generic input/output to a setup.actor.*

Here's a playground example.

import { fromPromise, setup } from 'xstate'

function createGenericMachine<
  Input,
  Output,
>() {
  return setup({
    types: {} as {
      events: { type: 'trigger'; input: Input }
    },
    actors: {
      resolver: fromPromise(
        async (args: { input: Input }): Promise<Output> => {
          throw new Error('not implemented')
        },
      ),
    },
  }).createMachine({
    initial: 'idle',
    on: {
      trigger: {
        target: 'resolving',
      },
    },
    states: {
      idle: {},
      resolving: {
        // only happens when generic arguments are supplied to 
        // setup.actors.resolver
        invoke: {
          src: 'resolver',
          input: ({ event }) => event.input,
          onDone: { target: 'valid' },
          onError: { target: 'invalid' },
        },
      },
      valid: {},
      invalid: {},
    },
  })
}

type input = {
  in: string
}

type output = {
  out: string
}

// type inference is working here
const machine = createGenericMachine<input, output>().provide({
  actors: {
    resolver: fromPromise(async({ input }) => {
      console.log(input.in)
      return {} as output
    })
  }
})

Expected result

I should be able to supply generic arguments as input for a child actor without breaking xstate types.

Actual result

Supplying a generic argument as input breaks type inference on invoke. Works fine outside this context and is correctly inferred from provide.

Removing the generic input parameter seems to resolve the type error. But that leaves input untyped when using provide.

Reproduction

https://www.typescriptlang.org/play?ts=5.4.5#code/JYWwDg9gTgLgBAbzgMyhEAFNJgGcCmANHATAK5hwC+K2cA5AB64wCGM+9AUF8mQHYBjGMAj84gqPnb4A4vn74owQQFlWggBbBFAHi5w4ASX5gyMQgbgB5c2YtcAfAAoAlIitTyUcaQrOEK0MYAE8wfFwALkQaVlwPQ0S4fAA3BRgoxDhQ8Oj6GGUAc0KlegBuOB17aJN7aiDqSySNGGhMwKTDKVwIABs0qGjUdCx0PHxnBubcEKE4Z1YoQvbK03MatfgqV2jRnAJdWxh7RzgAXlOOzqSYTTQAdzhFR4BRKDQoZ3p+CHhQMF6+BA6XwABN6K4pokqE1Oq5YYYYVZtgA6STSDjqLQ6CZXQw6YAiVi9PLAUGA+gIuBiaJ4xIFYDFJS0qHBRYlGB5bp9FI6QqUqFIpJCxIsGTtKFkwG0kVJbn9Pks66GAD0Kup-F6ITgmlYYHC-Hi900CjgJUUykEcHZZGB-Ay1qkJAoAOAYOyEDgrLgapI+HIYBRLTaKPlA29OhSEAA1vglcrDLgoIIuREeaUqdcqut5khUulqO4Lsk0vaUdmHAnDGIACJiONZNhLf15FLEsn0Rre6v8N4fWnZdkthiR9vgrsJ2XQzNwNu9Mkymej+egxcNEXbLhUHhcHL4VZ1M4JVbRFjKfiFLc8PfUuzmc7HiA5s98q9cX03nTIJQKQT7vBwPc0DRnyOo-lwghiCwcAgBo2iKA+6IyPIFoqFi8H4LoFbEE+xzmC4rgomAaC8qCuJWMGUASnKab9MytAjNg4wLDMQgBAe97bOclxQpBhp9PgKK9BAhTOBW5b8JC1xeGQPgxNa8S4fY65SfU2xAA

Additional context

No response