statelyai / xstate

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

Bug: Change in `@xstate/vue` types between 4.23.4 and 4.30.2 starts throwing Typescript errors #3080

Closed K3TH3R closed 2 years ago

K3TH3R commented 2 years ago

Description

I have the following machine, which throws no Typescript errors on XState 4.23.4:

import { useInterpret } from '@xstate/vue'
import { inject, InjectionKey, provide } from 'vue'
import { assign, createMachine, InterpreterFrom } from 'xstate'

interface AppContext {
  count: number
}

type AppEvents = { type: 'TOGGLE' }

export const appMachine = createMachine(
  {
    id: 'app',
    schema: {
      context: {} as AppContext,
      events: {} as AppEvents,
    },
    context: {
      count: 0,
    },
    initial: 'inactive',
    states: {
      inactive: {
        on: { TOGGLE: 'active' },
      },
      active: {
          entry: 'incrementCount',
          on: { TOGGLE: 'inactive' },
      },
    },
  },
  {
    actions: {
      incrementCount: assign({
        count: (ctx) => ctx.count + 1,
      }),
    },
  },
)

type AppService = InterpreterFrom<typeof appMachine>
export const appMachineKey: InjectionKey<AppService> = Symbol()

export function provideAppServices() {
  const appService = useInterpret(appMachine)
  provide(appMachineKey, appService)
  return appService
}

export function useAppService() {
  const service = inject(appMachineKey)

  if (!service) {
    throw new Error('Make sure to inject the App service')
  }

  return service
}

Expected result

I expected to be able to upgrade my machine as-is without encountering new Typescript errors.

Actual result

Upon upgrading to 4.30.2, with no other changes to my machine, I start seeing the following lines highlighted with errors: Screen Shot 2022-02-23 at 2 12 59 pm

If I add the tsTypes: {} line to generate the typegen file, the error on my actions disappear, but I'm still seeing the following errors:

  1. const appService = useInterpret(appMachine)
    Argument of type 'StateMachine<{ count: number; }, any, AppEvents, { value: any; context: { count: number; }; }, 
    BaseActionObject, ServiceMap, Typegen0 & { ...; }>' is not assignable to parameter of type 
    'MaybeLazy<StateMachine<{ count: number; }, any, AppEvents | { type: "xstate.init"; }, { value: any; context: 
    { count: number; }; }, BaseActionObject, ServiceMap, TypegenDisabled & ... 2 more ... & { ...; }>>'.
    Type 'StateMachine<{ count: number; }, any, AppEvents, { value: any; context: { count: number; }; }, BaseActionObject, 
    ServiceMap, Typegen0 & { ...; }>' is not assignable to type 'StateMachine<{ count: number; }, any, AppEvents | 
    { type: "xstate.init"; }, { value: any; context: { count: number; }; }, BaseActionObject, ServiceMap, TypegenDisabled 
    & ... 2 more ... & { ...; }>'
  2. provide(appMachineKey, appService)
    const appService: Interpreter<{
    count: number;
    }, any, AppEvents | {
    type: "xstate.init";
    }, {
    value: any;
    context: {
        count: number;
    };
    }, TypegenDisabled>
    Argument of type 'Interpreter<{ count: number; }, any, AppEvents | { type: "xstate.init"; }, { value: any; context: 
    { count: number; }; }, TypegenDisabled>' is not assignable to parameter of type 'Interpreter<{ count: number; }, 
    any, AppEvents, { value: any; context: { count: number; }; }, Typegen0 & { indexedActions: 
    IndexByType<BaseActionObject>; indexedEvents: MergeWithInternalEvents<...>; }>'.
    The types of 'machine.__TEvent' are incompatible between these types.

Reproduction

https://codesandbox.io/s/vue-typegen-issues-ty4k8r?file=/src/App.machine.ts

Additional context

"xstate": "4.30.2",
"vue": "3.2.29",
"@xstate/vue": "0.8.2",
Andarist commented 2 years ago

@xstate/vue@1.x doesn't support machines with typegen and we can't do much to fix that. A package consuming a machine must declare explicitly what it wants to do with the typegen stuff in its definition - it can either utilize the typegen information or just accept any at that position but the choice has to be explicit.

No worries though because I've just prepared a PR adding the typegen support to @xstate/vue: https://github.com/statelyai/xstate/pull/3083

K3TH3R commented 2 years ago

Okay, thank you @Andarist.