Skip to content

How to use external machine config with correct type (using TypeScript)? #78

@fabiradi

Description

@fabiradi

First of all, thanks for this great little library built for React! The machine syntax is really nice and also the TypeScript support. 👍

My problem is that I want to first define the machine config and then use the config object for the hook. Using your sample machine, it would look like this:

const machine = {
  initial: 'inactive',
  states: {
    inactive: {
      on: { TOGGLE: 'active' },
    },
    active: {
      on: { TOGGLE: 'inactive' },
      effect() {
        console.log('Just entered the Active state');
        // Same cleanup pattern as `useEffect`:
        // If you return a function, it will run when exiting the state.
        return () => console.log('Just Left the Active state');
      },
    },
  },
}

const [state, send] = useStateMachine(machine)

The error that I get is:

Argument of type '{ initial: string; states: { inactive: { on: { TOGGLE: string; }; }; active: { on: { TOGGLE: string; }; effect(): () => void; }; }; }' is not assignable to parameter of type 'InferNarrowestObject<Definition<{ initial: string; states: { inactive: { on: { TOGGLE: string; }; }; active: { on: { TOGGLE: string; }; effect(): () => void; }; }; }, { inactive: { on: { TOGGLE: string; }; }; active: { on: { TOGGLE: string; }; effect(): () => void; }; }, undefined, false>>'.
  Types of property 'initial' are incompatible.
    Type 'string' is not assignable to type '"inactive" | "active"'.ts(2345)

I tries the following types without any success:

const machine1: Machine.Definition.Impl = { /* */ }
const machine2: Machine.Definition<unknown, { inactive: 'inactive'; active: 'active' }> = { /* */ }

I also tried to get around the error by definition my own type. But it is incomplete and I don't want to redefine something that already exists somewhere else.

  interface IMachine {
    initial: string
    states: {
      [key: string]: {
        on: { [key: string]: string | { target: string /*guard?: any*/ } }
        effect?: () => void // works, but misses the arguments...
      }
    }  
  }

🤷🏻 How do I solve this problem in a clean way with defining my own types? They are already there. I just cannot figure how to apply them correctly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions