statelyai / xstate

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

Bug: Second argument of sendTo as a plain object causes typescript error #4725

Open zollipaul opened 5 months ago

zollipaul commented 5 months ago

XState version

XState version 5

Description

This was discussed on discord: https://discord.com/channels/795785288994652170/1201264941223645366/1201264941223645366 And now, as suggested the issue. Having a plain object as second argument of sendTo function in a state machine causes a typescript error:

someEvent: {
          actions: sendTo(({ system }) => system.get('childMachine'), ({
            type: 'notify',
            data: 'error', // ts error
          })),
        },

this works, if it is a function

  someOtherEvent: {
          actions: sendTo(({ system }) => system.get('childMachine'), () => ({
            type: 'notify',
            data: 'thats working', // no ts error
          })),
        },

Expected result

no ts error

Actual result

ts error: Object literal may only specify known properties, and 'data' does not exist in type 'EventObject | SendExpr<MachineContext, EventObject, undefined, { type: string; } & EventObject, EventObject>'.(2353)

Reproduction

https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgYygUwIYzQWQ8gC2ADs0AaOAZzRgFcwLKwMB3YgYSIBsATRtYjwAqECgEFkMaACU0AMwBiUCCDgBfOHOWqARAA9KMLGh0BuAFDnkEYoZTceeQiTRwAvFRr0AFAnNw4GABPMDRKAC5EfwC4NAA3ARgIxA0MSiiYmODQyJ1iCBhgOSCdMmjMniwMSMMoEgBzcvVotXM1AEoAOlRMbCciUl9okmBCjC5cgEZS6MNjZL9MuWAoQwBlI2xIxcy4G22mzPzC4oPd3aMoeppc6mtBDeMdQ5jW87fXssy7mx5HrZSLTa7Us9zsIHwA1cHh6xn6LiGAWAPFy+CkUBmSOIo2A41yy1WMH+Ji+sWIMCgQRqzDYnGAvG8zl48NIFB2SJRcB0TMckJcmJilCChjQIAAkpzuQ4WSYWu1SXNsAsmgT1ps0GddvsMudYglyWJtnAAPTGzyCOAsZTEep6xKW0YETS0YiSYA2KhBckYPQvTJo922GoCYQQby+T0i1QddwAPkj2BAnWuMG8AHIeTK0-K4N52nHc+zdQFshq4GmrTZ6gBRfUwNMUU2xKDKKBUAgQWi8OAAI1cBDQ6D9u0qRkiacmACYAMwNuDDgIdeXDtSk87xRIAISNTeoFsrNrt5IdMCdYC4GBIex7ACs0JIF3AAzZknvQ+GkEKo+p82541-E2TGh00zPlSGzChEWLLIQjLCtrRrOsG0fAJR2qcsp1nRszUHVs4AHdAKB7Wh4EoDsux4XtXAwYhmzwuRoCPeBS3naCf2XYtV2HDdyXYHczTfFBoHQSQmJPM8LyvCBb3vGBH2fINzXfCMANFH8C1UpMUxA6UwLQCDCxQwJYPHY4iiCZC2NQqpx0wucm1wxiCPIXsSPbTtuz7OB8jo6BHyXNddi44seJgAARfilKEltZLElhHWM0In0oahYEDeS3RfYNBBED8EzUmM-3yrTgIzXTnHA-M0jgCR0VkRRtAAHlLCA5HseleQqtBY0goti1LUyCnM+yzRYaAAGtKAAQiMtDbJnOd-PaDjdWC3VQurSLBIPW1QvExLqJSwdChsDKTsUt9cpU4VE3UorNKA1Myo6rMqvSWqZHkJQVGa2DWva5k9J6wyrIO8cdtrRIRuikT4EcqBZpsjCFsC95ltRz4XjWxdSS4jpTCAA

Additional context

No response

davidkpiano commented 5 months ago

If you specify the type, you'll see that the event is not allowed:

          actions: sendTo(({ system }) => system.get('childMachine') as ActorRefFrom<typeof childMachine>, ({
            type: 'notify',
            data: 'error',
          })),

In general, using as ActorRefFrom<...> is a viable work-around. See here: https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgYygUwIYzQWQ8gC2ADs0AaOAZzRgFcwLKwMB3YgYSIBsATRtYjwAqECgEFkMaACU0AMwBiUCCDgBfOHOWqARAA9KMLGh0BuAFDnkEYoZTceeQiTRwAvFRr0AFAnNw4GABPMDRKAC5EfwC4NAA3ARgIxA0MSiiYmODQyJ1KFTQAUQTiGB0yaMyeLAxIwygSAHNK9Wi1czUASgA6VExsJyJSX2iSYBhgDC5cgEZy6MNjZL9MuWAoQwBlI2xIlcy4Gz2WzPyQIpKYY4ODoyhGmlzqa0Ft4x0TmPab76+K07QLx4b12KTaHU6lhedhA+CGrg8fWMgxcIwCwB4uXwUig83RxHGk2mcB0aw2MBBJn+sVKUCCdWYbE4wF43mcvBRpAo+3RmJJ7MccJceJilCChjQIAAknydALOSY2p1qYtsMsWmStjs0NcDkcMjcqAVioldYa4NjgDZktRBCJvL4qOLsKouu4AHxOiUgboPGDeADk8qFpADyrg3k6HojPPNgRCOrgAeIEAmciCAepcbg1SMkQDMAIWHSLGgAGsmpnPpkusrq+oswczmgAPKFtBQE2lM2Gy3WuoCYQQB1IMXe9RRtyescu300QPB5yhqNpOASHGyRTaAA82TQEDk9hZgqXaHdFDR2fjOSTKbTGcb5tztSTHeUUCr2drj7+nzUjf-NoKi6UwgA

zollipaul commented 5 months ago

Thanks, type assertion like as ActorRefFrom<typeof childMachine> works like a charm! No I do not need to import events from childMachine to create the correct event. So it boils down to correct types within system.get() (if that is possible), then all errors would be resolved.

(I edited the reproduction to better explain the errors)

zollipaul commented 5 months ago

Ok, type assertion gets problematic when you want to send events back and forth between parent and child, because of circular type reference

CodingDive commented 1 month ago

@zollipaul have you had any success in removing circular type reference issues? Usually, I have to treat one machine as "any" throughout my code to prevent this issue.

All in all, sendTo typing works magically, but there are still a few edge cases.