mattpocock / xstate-codegen

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

Type support for `useService`? #48

Closed danielkcz closed 3 years ago

danielkcz commented 3 years ago

I see that useService is generated in react.d.ts, but I kinda fail to see how to use that.

What I mean is that in the top component I get service reference which is of some kind of type. Now I need to pass it down, but how to specify the type for it in props of the receiving component?

Without the codegen I was used to declaring manually export type TMachineService = Interpreter<TContext, TStates, TEvents> and then used that in declaring type in props. However, now I don't have access to TStates, but I would probably lose a lot of benefits from that anyway.

So what is the idea here?

cc @redappleorigin

danielkcz commented 3 years ago

What I see as options here is either generate a similar map to RegisteredMachinesMap, but using Interpreter instead or to have some utility type that can convert machine type to interpreter type.

mattpocock commented 3 years ago

I agree that there needs to be some kind of useful way to references the types in RegisteredMachineMap. I'll have a think about some potential API's.

danielkcz commented 3 years ago

I guess I will stick to Interpreter<TContext, {}, TEvents> for now unless you have some idea for a quick workaround?

mattpocock commented 3 years ago

@FredyC This will work for now:

https://codesandbox.io/s/xstate-codegen-example-forked-zgkky?file=/src/demo.machine.ts

danielkcz commented 3 years ago

@mattpocock Yea, that's essentially the same what I am using since the shape of states is unknown.

Don't worry, I will survive :) I am grateful for what you are doing here and already feeling small but important productivity gains.

mattpocock commented 3 years ago

@FredyC Does it not work? The InterpreterWithMatches should work natively with the useService @xstate/compiled/react exports.

Thanks for your kind words :)

danielkcz commented 3 years ago

Yea just stumbled upon it. I wasn't sure why I need your approach, but I haven't realized that service from your useMachine won't be compatible with pure Interpreter. Makes sense now and it's indeed working.

danielkcz commented 3 years ago

@mattpocock Did you implement a better solution? The previous one is working, but it's subpar since it loses all information about possible states.

mattpocock commented 3 years ago

You're right - this should be re-opened. My proposed solution is to autogenerate some helper types which allow you to more easily pass down references to services.

Imagine a machine declared with an ID of 'someMachineName':

// Instead of:
export type TMachineService = Interpreter<TContext, any, TEvents>

// This:
import { SomeMachineNameInterpreter } from '@xstate/compiled';

type Service = SomeMachineNameInterpreter<TContext, TEvents>;

This Service type could be added to props, then hopefully passed in to useService and be typed properly.

danielkcz commented 3 years ago

@mattpocock That would be great although I wonder why SomeMachineNameInterpreter would require generic arguments? Since it will be generated for a specific machine, these can be included by default.

Also, the @xstate/react has a new useActor hook which expects the Actor type instead of the Interpreter, so we should generate both I think.

I might give a stab at it if you are too busy, but I'll probably need some basic pointers.

mattpocock commented 3 years ago

Annoyingly, the generated types don't have access to TContext and TEvent, because we can't copy them from the user's definitions. That means they need to be passed in as generics every time. Boo... But possibly subject to change in the future.

Correct, useActor needs including.

Happy to do a loom explaining how I'd approach this if you'd like some tips?

danielkcz commented 3 years ago

Happy to do a loom explaining how I'd approach this if you'd like some tips?

That would be great.

Shame about generic types, would be lovely to be able import directly from @xstate/compiled anywhere without the need to reexport. Oh well.

mattpocock commented 3 years ago

@FredyC https://www.loom.com/share/22bca0cab3f746c4812b2a771a3a4a1b

danielkcz commented 3 years ago

Closing as the useService is supported now (although not published yet). The useActor will be handled in #70.