Search code examples
typescriptzustand

Using generics with zustand's create method


I have a zustand store which holds GridRow<T> type items. This represents selected rows in a main grid, so it uses generics to represent the specific data used in the grid.

I'm not sure how to pass the generic to the store's create method. I can't wrap it an another function because it would create a new store each time.

interface MainGridState<T> {
  selectedRows: Array<GridRow<T>>
}

const initialState = {
  selectedRows: []
}

// T is undefined here, as I have no way to declare it
const useMainGridStore = create<MainGridState<T>>()(set => ({
  ...initialState,
}))

export const useMainGridSelectedRows = <T>(): Array<GridRow<T>> =>
  useMainGridStore<T>(state => state.selectedRows)

Solution

  • Try this:

    interface MainGridState<T> {
      selectedRows: Array<GridRow<T>>
    }
    
    export type UseDataReturn<T> = {
      data: MainGridState<T>;
    };
    
    const initialState: UseDataReturn<{}>["data"] = {
      selectedRows: []
    };
    
    export const useMainGridSelectedRows = create<UseDataReturn<{}>>((set) => ({
      data: initialState,
    }));
    
    export const useMainGridStore = useMainGridSelectedRows as {
      <T>(): UseDataReturn<T>;
      <T, U>(selector: (s: UseDataReturn<T>) => U): U;
    };
    
    // then use it
    function Test() {
    
      // Use desired type instead of 'string'
    
      const dataExample = useMainGridStore<GridRow<string>[]>().data;
    
      const stateExample = useMainGridStore<string, GridRow<string>[]>(state => state.data.selectedRows)
    }