Search code examples
reactjstypescriptreduxredux-thunk

React - could not send a redux-thunk action with extra argument


I trying to working with typescript with redux-thunk and redux. I would like to pass an object to any action (I am using dependency injection and I need to pass an object service or string)

i got this error;

  Overload 1 of 2, '(action: AnyAction): AnyAction', gave the following error.
    Argument of type '(dispatch: any, getState: AppState, extraArg: string) => Promise<any>' is not assignable to parameter of type 'AnyAction'.

it's done as follows:

store.ts:

const middlewares = [
    routerMiddleware(history),
    thunkMiddleware.withExtraArgument('bar') as ThunkMiddleware<
      AppState,
      Actions,
      string
    >
  ];
  const middleWareEnhancer = applyMiddleware(...middlewares);

  const store = createStore(
    rootReducer(history),
    preloadState,
    composeWithDevTools(middleWareEnhancer)
  );

my index.ts where I am trying to send action is :

(store.dispatch as ThunkDispatch<{}, void, AnyAction>)(getAll());

my action file that working:

export const getall = () => async (dispatch: any) => {
  try {
    dispatch({ type: GETALL_REQUEST });
    return dispatch({ type: GETALL_SUCCESS, payload: null });
  } catch (e) {
    return dispatch({ type: GETALL_FAILURE, error: e });
  }
};

my action (put part of it) that raises the error

export const getAll = () => async (
  dispatch: any,
  getState: AppState,
  extraArg: string
) => {....action logic}

then I got the error on:

(store.dispatch as ThunkDispatch<{}, void, AnyAction>)(getAll());

Solution

  • The easiest way to correct the error:

    (store.dispatch as ThunkDispatch<AppState, string, AnyAction>)(getAll());
    

    and

    export const getAll = () => async (
      dispatch: any,
      getState: () => AppState,
      extraArg: string
    ) => {....action logic}
    
    1. ThunkDispatch accepts following type arguments: S - state, E - extended arg, A - action. So your use of ThunkDispatch should match types of your state and extended arg.

    2. Thunk action is a function which accepts following arguments: dispatch is a function, getState is also a function which returns state and extraArg. So make sure, that getState is a function.

    To avoid dispatch casting I suggest to properly type a store when creating. As you're using applyMiddleware which accepts an array, you should pass type argument to it. It accepts type of dispatch which will be used after applying Delawares.

    const middlewares = [thunk.withExtraArgument("bar")];
    const middleWareEnhancer = applyMiddleware<
      ThunkDispatch<AppState, string, Actions>
    >(...middlewares);
    

    As a result, you'll get a store with properly typed dispatch function. And you'll be able to use it without casting.

    store.dispatch(getAll());
    

    The working demo