xstate icon indicating copy to clipboard operation
xstate copied to clipboard

[Typescript] Bug: Using assign with only partial context causes TS error

Open schontz opened this issue 2 years ago • 0 comments

Description

When a machine has a context type, attempts to use assign with literal values doesn't work.

Visualizer code for reference:

import { createMachine, assign } from 'xstate';

const assignTSError = createMachine({
  id: 'machine',
  schema: {
    context: {} as { foo: boolean, bar: number }
  },
  entry: 'assignFooTrue',
  context: {
    foo: false,
    bar: 1,
  },
  initial: 'ready',
  states: {
    ready: {},
  }
}, {
  actions: {
    // error
    assignFooTrue: assign({
      foo: true,
    }),
    // error
    assignFooTrueNoArgs: assign({
      foo: () => true,
    }),
    // ok
    assignFooTrueWorking: assign({
      foo: (_) => true,
    })
  }
});

Expected result

I expect this to work:

    assignFooTrue: assign({
      foo: true,
    }),

Actual result

But it causes an error:

Type 'AssignAction<{ foo: boolean; }, EventObject>' is not assignable to type '((context: { foo: boolean; bar: number; }, event: AnyEventObject, meta: ActionMeta<{ foo: boolean; bar: number; }, AnyEventObject, BaseActionObject>) => void) | ActionObject<...> | undefined'.
  Type 'AssignAction<{ foo: boolean; }, EventObject>' is not assignable to type 'ActionObject<{ foo: boolean; bar: number; }, AnyEventObject>'.
    Types of property 'exec' are incompatible.
      Type '((context: { foo: boolean; }, event: EventObject, meta: ActionMeta<{ foo: boolean; }, EventObject, BaseActionObject>) => void) | undefined' is not assignable to type '((context: { foo: boolean; bar: number; }, event: AnyEventObject, meta: ActionMeta<{ foo: boolean; bar: number; }, AnyEventObject, BaseActionObject>) => void) | undefined'.
        Type '(context: { foo: boolean; }, event: EventObject, meta: ActionMeta<{ foo: boolean; }, EventObject, BaseActionObject>) => void' is not assignable to type '(context: { foo: boolean; bar: number; }, event: AnyEventObject, meta: ActionMeta<{ foo: boolean; bar: number; }, AnyEventObject, BaseActionObject>) => void'.
          Types of parameters 'meta' and 'meta' are incompatible.
            Type 'ActionMeta<{ foo: boolean; bar: number; }, AnyEventObject, BaseActionObject>' is not assignable to type 'ActionMeta<{ foo: boolean; }, EventObject, BaseActionObject>'.
              The types of 'state.configuration' are incompatible between these types.
                Type 'StateNode<{ foo: boolean; bar: number; }, any, AnyEventObject, any, any, TypegenDisabled>[]' is not assignable to type 'StateNode<{ foo: boolean; }, any, EventObject, any, any, TypegenDisabled>[]'.
                  Type 'StateNode<{ foo: boolean; bar: number; }, any, AnyEventObject, any, any, TypegenDisabled>' is not assignable to type 'StateNode<{ foo: boolean; }, any, EventObject, any, any, TypegenDisabled>'.
                    The types of 'config.invoke' are incompatible between these types.
                      Type 'SingleOrArray<AnyStateMachine | InvokeConfig<{ foo: boolean; bar: number; }, AnyEventObject>> | undefined' is not assignable to type 'SingleOrArray<AnyStateMachine | InvokeConfig<{ foo: boolean; }, EventObject>> | undefined'.
                        Type 'InvokeConfig<{ foo: boolean; bar: number; }, AnyEventObject>' is not assignable to type 'SingleOrArray<AnyStateMachine | InvokeConfig<{ foo: boolean; }, EventObject>> | undefined'.
                          Type 'InvokeConfig<{ foo: boolean; bar: number; }, AnyEventObject>' is not assignable to type 'InvokeConfig<{ foo: boolean; }, EventObject>'.
                            Types of property 'src' are incompatible.
                              Type 'string | AnyStateMachine | InvokeSourceDefinition | InvokeCreator<{ foo: boolean; bar: number; }, AnyEventObject, any, any, AnyEventObject>' is not assignable to type 'string | AnyStateMachine | InvokeSourceDefinition | InvokeCreator<{ foo: boolean; }, EventObject, any, any, EventObject>'.
                                Type 'InvokeCreator<{ foo: boolean; bar: number; }, AnyEventObject, any, any, AnyEventObject>' is not assignable to type 'string | AnyStateMachine | InvokeSourceDefinition | InvokeCreator<{ foo: boolean; }, EventObject, any, any, EventObject>'.
                                  Type 'InvokeCreator<{ foo: boolean; bar: number; }, AnyEventObject, any, any, AnyEventObject>' is not assignable to type 'InvokeCreator<{ foo: boolean; }, EventObject, any, any, EventObject>'.
                                    Types of parameters 'context' and 'context' are incompatible.
                                      Type '{ foo: boolean; }' is not assignable to type '{ foo: boolean; bar: number; }'.

Reproduction

https://stately.ai/viz/20ac2368-0f36-4688-a3c0-73809d9a1e13

Additional context

No response

schontz avatar Jul 01 '22 23:07 schontz