In redux-toolkit docs they suggest you to create the following definition to have proper types when you use useSelector hook:
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
This will save you of having to type all the selectors with the root state.
However, when it's time to define memoized selector with createSelector
there are no instructions about how to do a similar thing.
Is there any shortcut for this or I have to manually type every memoized selector?
I was working on a app that I wanted to do the same. For my needs, I just wanted a simple selector, so I did this:
// store.ts
// …omitted store configuration
export type RootState = ReturnType<typeof store.getState>;
// create a generic type called AppSelector
export type AppSelector<Return> = (state: RootState) => Return
// create a custom `createSelector` that uses the type above
export const createAppSelector = <R>(selector: AppSelector<R>): AppSelector<R> => selector
With the types above, we can do the following:
const selectTitle: AppSelector<string> = (state) => state.title;
// Note that using the AppSelector type requires you to always pass the return type argument
// It's much easier to use the createAppSelector function
// selectTitle and selectTitle2 accomplish the same thing
const selectTitle2 = createAppSelector((state) => state.title);
When inside createAppSelector
, state
will correctly have the RootState
type.
The limitation of this form is that, unlike createSelector
, createAppSelector
only allows you to create a single selector and doesn't allow you to combine or mutate the selections.
Hopefully someday we'll have a way to const createAppSelector: TypedCreateSelector<RootState> = createSelector;