Say I have code like so:
import { Action, Dispatch } from 'redux';
import { ThunkAction } from 'redux-thunk';
interface StateTree {
field: string;
}
function myFunc(action: Action | ThunkAction<void, StateTree, void>,
dispatch: Dispatch<StateTree>) {
dispatch(action); // <-- This is where the error comes from
}
...I get this error from the TypeScript compiler:
ERROR in myFile.ts:x:y
TS2345: Argument of type 'Action | ThunkAction<void, StateTree, void>' is not assignable to parameter of type 'Action'.
Type 'ThunkAction<void, StateTree, void>' is not assignable to type 'Action'.
Property 'type' is missing in type 'ThunkAction<void, StateTree, void>'.
I believe the problem is because of the way the redux-thunk
type definition file augments the redux
Dispatch
interface and the inability for TypeScript to know which definition of Dispatch
to use.
Is there a way around this?
In order to correctly dispatch thunks, you need to use the specific customized AppDispatch type from the store that includes the thunk middleware types, and use that with useDispatch .
To dispatch async actions into our store, we have to apply the thunk middleware by writing: const store = createStore(joke, applyMiddleware(thunk)); to apply the middleware. Then in App , we call dispatch with the function returned from the fetchJoke passed inside.
Redux Thunk is a middleware that lets you call action creators that return a function instead of an action object. That function receives the store's dispatch method, which is then used to dispatch regular synchronous actions inside the function's body once the asynchronous operations have been completed.
ThunkAction signature changed with latest version (now is ThunkAction<void, Your.Store.Definition, void, AnyAction>
) and unless some evil double casting (action as {} as Action
), the more elegant way I found is to define the redux dispatch as a ThunkDispatch like this:
import { applyMiddleware, Store, createStore, AnyAction } from 'redux';
import logger from 'redux-logger';
import thunk, { ThunkDispatch } from 'redux-thunk';
import { Redux } from '../definitions';
import rootReducer from './reducers';
import { bootstrap } from './actions';
export default function configureStore() {
const middleware = applyMiddleware( thunk, logger );
const store: Store<Redux.Store.Definition> = createStore(rootReducer, middleware);
// Here the dispatch casting:
(store.dispatch as ThunkDispatch<Redux.Store.Definition, void, AnyAction>)( bootstrap() );
return store;
}
In case someone else is looking for an updated answer! ^^
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With