atlassian / react-sweet-state

Shared state management solution for React

Home Page:https://atlassian.github.io/react-sweet-state/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Can you tighten typescript types or add runtime development warning what is valid state in store?

rluiten opened this issue · comments

I was just trying out react-sweet-state as it looks interesting and created a small to do list app to play with it.

I put an array of Todo objects in an array as the state of the store.
This produces no errors from typescript and even runs without error until you setState new values of the state.

The state of the store being an array is not supported as I later discovered in the react-sweet-state documentation under setState().

I think you might help developers by either tightening the types allowed for the state of store, or maybe adding a runtime warning in development mode from react-sweet-state.

I stripped down the app I was playing with to make a small example to demonstrate the behavior I am describing.
https://codesandbox.io/s/eloquent-hill-vh4xb?file=/src/App.tsx

If you change the text of a to do item it calls setState and that crashes this app because after set state the value of state is of the form { 0: [Todo1, Todo2] }

I quite like sweet state so far 👍
Thank you for making it available.

Thank you for playing around with sweet-state. Having typescript/flow to complain if you an unsupported type to setState can indeed be helpful. I need to look into how to do that without breaking existing consumers types.
Do you have suggestions on the type def?

Given the createStore definition copied below for reference.
The TState extends object express the intention but an array is an object so I think that's why it isn't a problem to pass an array.

  /**
   * createStore
   */

  function createStore<
    TState extends object,
    TActions extends Record<string, ActionThunk<TState, TActions>>
  >(config: {
    initialState: TState;
    actions: TActions;
    name?: string;
  }): Store<TState, TActions>;

I have had a further think about it, and a run time development environment error is probably the stronger choice for sweet state as it will help people who aren't using typescript as well. Having a type level enforcement would be nice to have.

This looks like it might be useful https://stackoverflow.com/a/55532011
I've applied that referenced solution to the declaration of createStore() here.

  // Exclude arrays as parameter for TState
  function createStore<
    TState extends object,
    TActions extends Record<string, ActionThunk<TState, TActions>>
  >(config: {
    initialState: TState & (TState extends any[] ? 'NO Arrays !' : {});
    actions: TActions;
    name?: string;
  }): Store<TState, TActions>;

  function createStore<
    TState extends object,
    TActions extends Record<string, ActionThunk<TState, TActions>>
  >(config: {
    initialState: TState;
    actions: TActions;
    name?: string;
  }): Store<TState, TActions>;

I tried it out with following code and on the surface it seems promising as the initialState type below is never[].
I have become stuck in how to turn that never[] into a typescript type error for the type tests in test.tsx

const TypeStore4 = createStore({
  initialState: [],
  actions: {},
  name: 'TypeStore4',
});