Michael Tontchev
Michael Tontchev

Reputation: 1109

How to call thunked action creator outside of react component with TypeScript

I have a thunked store created like

export const store = createStore<IState, IAction<string, any>, {}, {}>(combinedReducers, applyMiddleware(thunk));

I want to dispatch a thunked action outside of a React component, like store.dispatch(myThunkedActionCreator(data));

However, the type of dispatch is coming in as Dispatch<IAction<string, any>> instead of ThunkDispatch<State, void, ActionType>, which would be the type necessary to pass a thunk to the store's modified dispatch. I import the store as import { store } from '../Store/Store';

How can I get store.dispatch to have the right, thunked dispatch type?

I know I can typecast dispatch at its callsites, but that's a hack. I'm not currently using RTK, which solves the typing problem, but that's out of scope for me at the moment.

Upvotes: 0

Views: 303

Answers (1)

markerikson
markerikson

Reputation: 67489

There's a couple problems here.

The first is that we have officially deprecated the original createStore API from the core redux package, and we do not want people using that directly in their applications! Instead, you should be using the configureStore API from our official Redux Toolkit package, which wraps createStore and sets it up with a good default configuration:

The second issue is that by explicitly adding generics to createStore, you're overriding any possible type inference that TS might do from the provided middleware like thunk. So, as far as TS is concerned, store.dispatch is still only the "basic" type that can only accept action objects - the thunk middleware modifications (which tell TS it can also accept a thunk function) are being ignored and overridden by those generics.

The best answer here is to use configureStore, which automatically adds the thunk middleware anyway, and has better TS inference for any customizations:

import { configureStore } from "@reduxjs/toolkit" 

const store = configureStore({
  reducer: combinedReducers
})

// already added the thunk middleware!
store.dispatch(myThunk())

// TS types reflect that:
// ThunkDispatch & Dispatch<AnyAction>
type AppDispatch = typeof store.dispatch

Upvotes: 1

Related Questions