Search code examples
typescriptreduxredux-toolkit

Infer type of actions for `dispatch` using `reduxjs/toolkit`


I am using reduxjs/toolkit to set up my redux store and I would like to enforce that whenever dispatch is called, it only accepts actions that I have declared in my slices:

import { combineReducers, configureStore, createSlice } from "@reduxjs/toolkit";

const initialState = {
  value: false,
};

const testSlice = createSlice({
  name: "test",
  initialState,
  reducers: {
    toggled(state) {
      state.value = !state.value;
    },
  },
});

const appReducer = combineReducers(testSlice.reducer);
const store = configureStore({
  reducer: appReducer,
});

const MyComponent = () => {
  const dispatch = useDispatch();

  handleClick() {
     dispatch(someInvalidAction()) // does not complain
     dispatch(toggled())
  }
}

I am aware that I could just pass a generic typeof testSlice.actions to dispatch or have a combined union including all the action types like type AllActions = typeof testSlice.actions | typeof otherSlice.actions, but it feels like there should be a more straight forward way of doing this or perhaps someone knows the reason why it does not work like that out of the box?


Solution

  • Just don't do it. This simulates some kind of type safety that just doesn't exist in your application - internally, Redux will dispatch additional actions (e.g. INIT), and also all of your middleware might dispatch actions on their own.

    Having the dispatch type of your store as shown in https://redux-toolkit.js.org/usage/usage-with-typescript#getting-the-dispatch-type is really the most realistic you can get.

    const store = configureStore({
      reducer: rootReducer,
    })
    
    export type AppDispatch = typeof store.dispatch
    export const useAppDispatch = useDispatch.withTypes<AppDispatch>()