mattpocock / xstate-catalogue

Professionally designed, interactive state machines
https://xstate-catalogue.com
MIT License
811 stars 62 forks source link

typescript show error message with "authentication.machine.ts" #54

Closed Sunqinying closed 3 years ago

Sunqinying commented 3 years ago

In my vscode, the section "authentication.machine.ts" show an error with

(property) clearUserDetailsFromContext: AssignAction<{
    userDetails: undefined;
}, EventObject>
Type 'AssignAction<{ userDetails: undefined; }, AuthenticationMachineEvent>' is not assignable to type 'ActionObject<AuthenticationMachineContext, AuthenticationMachineEvent> | ActionFunction<AuthenticationMachineContext, AuthenticationMachineEvent>'.
  Type 'AssignAction<{ userDetails: undefined; }, AuthenticationMachineEvent>' is not assignable to type 'ActionObject<AuthenticationMachineContext, AuthenticationMachineEvent>'.

my ts config as below:

{
  "extends": "./node_modules/gts/tsconfig-google.json",
  "compilerOptions": {
    "rootDir": ".",
    "outDir": "build"
  },
  "include": [
    "src/**/*.ts",
    "test/**/*.ts"
  ]
}

ts version:

    "typescript": "^4.0.3"
mattpocock commented 3 years ago

@Sunqinying What xstate version are you running?

Sunqinying commented 3 years ago

@Sunqinying What xstate version are you running?

4.19.1

mattpocock commented 3 years ago

Try this:

clearUserDetailsFromContext: assign((context) => {
  return { userDetails: undefined }
})
Sunqinying commented 3 years ago

Try this:

clearUserDetailsFromContext: assign((context) => {
  return { userDetails: undefined }
})

It's ok now

Is this caused because

export interface ActionObject<TContext, TEvent extends EventObject> {
    /**
     * The type of action that is executed.
     */
    type: string;
    /**
     * The implementation for executing the action.
     */
    exec?: ActionFunction<TContext, TEvent>;
    [other: string]: any;
}

not compatibel with

export interface AssignAction<TContext, TEvent extends EventObject> extends ActionObject<TContext, TEvent> {
    type: ActionTypes.Assign;
    assignment: Assigner<TContext, TEvent> | PropertyAssigner<TContext, TEvent>;
}

and there should no difference whether passed a function or object, because the declaration for assign return the same type

export declare const assign: <TContext, TEvent extends EventObject = EventObject>(assignment: Assigner<TContext, TEvent> | PropertyAssigner<TContext, TEvent>) => AssignAction<TContext, TEvent>;
Sunqinying commented 3 years ago

Try this:

clearUserDetailsFromContext: assign((context) => {
  return { userDetails: undefined }
})

It's ok now

Is this caused because

export interface ActionObject<TContext, TEvent extends EventObject> {
    /**
     * The type of action that is executed.
     */
    type: string;
    /**
     * The implementation for executing the action.
     */
    exec?: ActionFunction<TContext, TEvent>;
    [other: string]: any;
}

not compatibel with

export interface AssignAction<TContext, TEvent extends EventObject> extends ActionObject<TContext, TEvent> {
    type: ActionTypes.Assign;
    assignment: Assigner<TContext, TEvent> | PropertyAssigner<TContext, TEvent>;
}

and there should no difference whether passed a function or object, because the declaration for assign return the same type

export declare const assign: <TContext, TEvent extends EventObject = EventObject>(assignment: Assigner<TContext, TEvent> | PropertyAssigner<TContext, TEvent>) => AssignAction<TContext, TEvent>;

xstate say the same proble

However, TypeScript inference isn't perfect, so the responsible thing to do is to add the context and event as generics into assign<Context, Event>(...):

// ...
on: {
INCREMENT: {
// Generics guarantee proper inference
actions: assign<CounterContext, CounterEvent>({
count: (context) => {
// context: { count: number }
return context.count + 1;
}
});
}
}
// ...