xstate
xstate copied to clipboard
Bug: Typegen fails to infer types of imported actions/etc
Description
If I use typegen with all options inside of the same file, the types work as expected. If I move any of these options to an external file, typegen cannot infer the method signatures on either end.
Expected result
The tyepgen service could follow the import to correctly infer the type signature of the imported action. Then within the action, I could add type hints to correctly see what the parameters are.
Actual result
A rather long error block is shown underneath the action declaration.
Reproduction
https://github.com/parker-codes/xstate-typegen-import-error
Additional context
There is an xstate:typegen
command defined in package.json to generate the types.
Remove either of the two lines that say // @ts-expect-error XState Typegen
to view the errors.
This is expected - typegen generates some extra data to aid inference. Inference only works when the contextual type can flow into an expression. In your case, incrementCount
is already predefined elsewhere and thus its type is already "set in stone".
@Andarist is there no way to facilitate sharing code between machines then and still have them typed? Perhaps using a different strategy to remove the "set in stone" functionality?
This does the trick:
Possible patch that utilizes `MachineOptionsFrom`
diff --git a/src/machines/actions.ts b/src/machines/actions.ts
index e941abc..90a8133 100644
--- a/src/machines/actions.ts
+++ b/src/machines/actions.ts
@@ -1,7 +1,9 @@
-import { assign } from "xstate";
+import { assign, MachineOptionsFrom } from "xstate";
+import type { ToggleMachine } from "./toggle.machine";
-export const incrementCount = assign((ctx) => ({
- // Object is of type 'unknown'.
- // @ts-expect-error XState Typegen
+export const incrementCount: MachineOptionsFrom<
+ ToggleMachine,
+ true
+>["actions"]["incrementCount"] = assign((ctx) => ({
count: ctx.count + 1,
}));
diff --git a/src/machines/toggle.machine.ts b/src/machines/toggle.machine.ts
index 8a8212d..f72734f 100644
--- a/src/machines/toggle.machine.ts
+++ b/src/machines/toggle.machine.ts
@@ -7,42 +7,42 @@ interface ToggleContext {
type ToggleEvent = { type: "TOGGLE" } | { type: "RESET" };
-export const toggleMachine = createMachine(
- {
- id: "toggle",
- preserveActionOrder: true,
- initial: "off",
-
- schema: {
- context: {} as ToggleContext,
- events: {} as ToggleEvent,
- },
- tsTypes: {} as import("./toggle.machine.typegen").Typegen0,
+const _toggleMachine = createMachine({
+ id: "toggle",
+ preserveActionOrder: true,
+ initial: "off",
- context: {
- count: 0,
- },
+ schema: {
+ context: {} as ToggleContext,
+ events: {} as ToggleEvent,
+ },
+ tsTypes: {} as import("./toggle.machine.typegen").Typegen0,
- states: {
- off: {
- on: {
- TOGGLE: {
- actions: ["incrementCount"],
- target: "on",
- },
+ context: {
+ count: 0,
+ },
+
+ states: {
+ off: {
+ on: {
+ TOGGLE: {
+ actions: ["incrementCount"],
+ target: "on",
},
},
+ },
+ on: {
on: {
- on: {
- TOGGLE: "off",
- },
+ TOGGLE: "off",
},
},
},
- {
- actions: {
- // @ts-expect-error XState Typegen
- incrementCount,
- },
- }
-);
+});
+
+export type ToggleMachine = typeof _toggleMachine;
+
+export const toggleMachine = _toggleMachine.withConfig({
+ actions: {
+ incrementCount,
+ },
+});