Search code examples
typescripttypescript-typingsreact-typescriptzustand

Getting properties from the store without missing their types


I have this setup for Redux (Zustand) store

type StateType = keyof DatasetSlice | keyof GlobalSlice
type Slices = GlobalSlice & DatasetSlice

const setStore = set => ({
    ...datasetSlice(set),
    ...globalSlice(set),
})

const useStore = create(devtools<Slices>(setStore, { enabled: true, name: 'Core store' }))

export const useGetStates = (stateKeys: StateType[]) =>
    useStore(
        state =>
            Object.assign(
                {},
                ...stateKeys.map(stateKey => {
                    return { [stateKey]: state[stateKey] }
                })
            ),
        shallow
    )

useGetStates is used to fetch data from the store, like this

const { backButtonTarget, invitedUsers } = useGetStates(['backButtonTarget', 'invitedUsers'])

The problem is that fetched variables (backButtonTarget, invitedUsers) have ANY type, but I need their types as they are defined in the store. Any ideas how it can be solved here?


Solution

  • You can achieve the desired result by adding the generic parameters to useGetStates:

    export const useGetStates = <T extends StateType[]>(
      stateKeys: T,
    ): { [K in T[number]]: Slices[K] } =>
      useStore(
        (state) =>
          Object.assign(
            {},
            ...stateKeys.map((stateKey) => {
              return { [stateKey]: state[stateKey] };
            }),
          ),
        shallow,
      );
    
    

    The crucial part is the return type which takes the elements from the passed array and assigns their slice type as a value: { [K in T[number]]: Slices[K] }

    playground