Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The future of Timsy #3

Open
christianalfoni opened this issue May 10, 2022 · 1 comment
Open

The future of Timsy #3

christianalfoni opened this issue May 10, 2022 · 1 comment

Comments

@christianalfoni
Copy link
Owner

christianalfoni commented May 10, 2022

So I am super happy to see the extremely early feedback on Timsy. This is how I think about the project at this state:

  • The core of Timsy is a simple state machine that has strong type inference and an API enforcing strong typing. It also supports nested state
  • The state machine only deals with state, where side effects is strictly subscribing to transitions where the new state, the event causing that state and the previous state gives you enough information to perform those side effects
  • The core of Timsy has abstraction specific to the frameworks where it can be consume, where React is the first abstraction

What Timsy could need in terms of implementation is reviewing the typing and code. It is important that the code is more readable, than "clever" and the same goes for decisions around typing. It is better to do a // @ts-ignore than using harder to read code to achieve proper typing. At the end of the day the consumer of the library does not care about the internal typing of the library.

@christianalfoni
Copy link
Owner Author

christianalfoni commented May 11, 2022

So I did a comparison of "clarity" and "explicitness" of the API. Comparing the old Resizer machine in react-states with timsy:

react-states

type State =
  | {
      state: 'IDLE';
    }
  | {
      state: 'DETECTING_RESIZE';
      initialX: number;
    }
  | {
      state: 'RESIZING';
      x: number;
    };

type Action =
  | {
      type: 'MOUSE_MOVE';
      x: number;
    }
  | {
      type: 'MOUSE_UP';
      x: number;
    }
  | {
      type: 'MOUSE_UP_RESIZER';
    }
  | {
      type: 'MOUSE_DOWN';
      x: number;
    };

const reducer = (state: State, action: Action) =>
  transition(state, action, {
    IDLE: {
      MOUSE_DOWN: (_, { x }): State => ({
        state: 'DETECTING_RESIZE',
        initialX: x,
      }),
    },
    DETECTING_RESIZE: {
      MOUSE_MOVE: (mouseDownState, { x }): State => {
        if (Math.abs(x - mouseDownState.initialX) > 3) {
          return {
            state: 'RESIZING',
            x,
          };
        }

        return mouseDownState;
      },
      MOUSE_UP: (): State => ({
        state: 'IDLE',
      }),
      MOUSE_UP_RESIZER: (): State => ({
        state: 'IDLE',
      }),
    },
    RESIZING: {
      MOUSE_MOVE: (_, { x }): State => ({
        state: 'RESIZING',
        x,
      }),
      MOUSE_UP: (): State => ({
        state: 'IDLE',
      }),
    },
  });

timsy

const states = createStates({
  IDLE: () => ({}),
  DETECTING_RESIZE: (initialX: number) => ({ initialX }),
  RESIZING: (x: number) => ({ x })
});

const runMachine = createMachine(states, {
  IDLE: {
    MOUSE_DOWN: (x: number) => () => states.DETECTING_RESIZE(x)
  },
  DETECTING_RESIZE: {
    MOUSE_MOVE: (x: number) => (state) => {
      if (Math.abs(x - state.initialX) > 3) {
        return states.RESIZING(x);
      }

      return state;
    },
    MOUSE_UP: () => () => states.IDLE(),
    MOUSE_UP_RESIZER: () => () => states.IDLE()
  },
  RESIZING: {
    MOUSE_MOVE: (x: number) => () => states.RESIZING(x),
    MOUSE_UP: () => () => states.IDLE()
  }
});

Really happy about how much it cleans up and even gives additional type safety ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant