How to dispatch an Action or a ThunkAction (in TypeScript, with redux-thunk)?

redux-thunk typescript
react redux typescript tutorial 2019
react-redux-thunk typescript example
redux action types
redux toolkit typescript
typesafe-actions redux-thunk
redux-thunk patterns
return dispatch redux

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?

I think you are correct in that despite being able to handle both types, typescript cannot work out which overload to use.

I think the best option for you is to cast back to the desired type when calling dispatch

function myFunc(action: Action | ThunkAction<void, StateTree, void>, 
                dispatch: Dispatch<StateTree>) {
  if (action instanceof ThunkAction<void, StateTree, void>) {
    dispatch(action as ThunkAction<void, StateTree, void>);
  } else {
    dispatch(action as Action);
  }
}

I hope I'm wrong and there is a better way to achieve this.

redux-thunk/typescript.ts at master · reduxjs/redux-thunk · GitHub, Contribute to reduxjs/redux-thunk development by creating an account on GitHub​. redux-thunk/test/typescript.ts Can dispatch another thunk action. Redux Thunk is a commonly used middleware for writing sync and async logic that interacts with the Redux store. Feel free to check out its documentation here. A thunk is a function that returns another function that takes parameters dispatch and getState. Redux Thunk has a built in type ThunkAction which we can use to define types for those

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! ^^

Typescript with Redux, & Redux-Thunk Recipe, store/session/actions.ts import { ThunkAction, ThunkDispatch } from 'redux-thunk' import { AnyAction } from 'redux';// Action Definitionexport interface SetAction { Typescript with Redux, & Redux-Thunk Recipe. { ThunkAction, redux’s dispatch method only received Action items which is object. Not a function. To provide a function call instead.

Time has passed and many things have changed since this question and various answers were posted. However, I found that none of the answers seemed satisfactory to me because the first two (michael-peyper and pierpytom) involved recasting/redefining which felt weird. The third (joaoguerravieira) seemed better since it didn't involve either of those, but it was unclear, to me at least, how it solved the problem.

This is what seemed most helpful to me when I ran into a problem which I think was practically identical to this: how to get a properly typed "dispatch" method on the created redux store. That is, how to get the TypeScript compiler to agree that store.dispatch could dispatch either Actions or ThunkActions. Even if this is not exactly the same problem being asked about in the original question (but I think it might be), all search engine queries about my problem kept leading me back to this post so I thought it might be helpful to put my solution here.

I have always found it super difficult to find the right types to use for things when using redux (maybe I'm just dumb) so for a long time I always just created my store like this:

createStore(
    combineReducers(stuff),
    defaultState,
    applyMiddleware(thunkMiddleware));

...which always put me in the situation where I could call store.dispatch on thunks but the TypeScript compiler yelled at me even though it would still work at runtime. Bits of each answer finally lead me to what I believe is the most up-to-date and no-casting way of solving the problem.

The typing of the dispatch method on the store object is dictated by what the call to redux's createStore returns. In order to have the right type on the store's dispatch method, you have to set the type parameters correctly on the call to applyMiddleware (which you either directly or eventually pass as the third parameter to createStore). @joaoguerravieira's answer led me to look in this direction. In order to get the dispatch method to have the right type to dispatch either ThunkAction or Action, I had to call createStore/applyMiddleware like this:

createStore(
    combineReducers(stuff),
    defaultState,
    applyMiddleware<DispatchFunctionType, StateType>(thunkMiddleware));

where

type DispatchFunctionType = ThunkDispatch<StateType, undefined, AnyAction>

By doing this, I got a store of this type:

Store<StateType, Action<StateType>> & { dispatch: DispatchFunctionType };

...which gets me a store.dispatch function of this type:

Dispatch<Action<any>> & ThunkDispatch<any, undefined, AnyAction>

...which can successfully dispatch an Action or a ThunkAction without yelling about type and without any redefinitions/casting.

Properly setting the type parameters on the call to applyMiddleware is critical!

Usage With TypeScript, Type safety for reducers, state and action creators, and UI components; Easy ThunkAction<void, RootState, unknown, Action<string>> => async dispatch => {. Thanks for the example. I'm also struggling to figure out if it's possible to correctly type a component that dispatches thunk actions, so an example there would be really helpful too.

These are the correct typings: https://github.com/reduxjs/redux-thunk/blob/master/test/typescript.ts

Most notably:

const store = createStore(fakeReducer, applyMiddleware(thunk as ThunkMiddleware<State, Actions>));

applyMiddleware will already override the dispatch with a ThunkDispatch.

How to dispatch an Action or a ThunkAction (in TypeScript , import { action, dispatch } 'redux'; import { thunkaction } 'redux-thunk'; interface statetree { field: string; } function myfunc(action: action  I also don't get the redux-thunk typings to work or just don't get the point. The Dispatch-Definition enforces you to dispatch a ThunkAction. But in Redux with Redux-Thunk Middleware you can either dispatch a classic action (object with ha type property) or a ThunkAction, so the Dispatch typing should support both cases, shouldn't it?

Как отправить действие или ThunkAction (в TypeScript с , Скажем, у меня есть код, как так: import { Action, Dispatch } from 'redux'; import { ThunkAction } from 'redux-thunk'; interface StateTree { field: string; } function  Вот как я приближаюсь это. Во- первых, есть несколько изменений , которые необходимо

Comment envoyer une Action ou une ThunkAction (en TypeScript , Dire que j'ai le code comme ceci: import { Action, Dispatch } from 'redux'; import { ThunkAction } from 'redux-thunk'; interface StateTree { field: string; } function  After you install redux-thunk in your project, and apply the middleware, every action you dispatch will pass through this bit of code. It calls actions that are functions (and returns whatever they return), and otherwise passes the action along to then next middleware, or to Redux itself (which is what next(action) does).

(in TypeScript, with redux-thunk)?How to dispatch a Redux action , Dispatching thunk action creator does not match in TypeScript or a ThunkAction (in TypeScript, with redux-thunk)?How to dispatch a Redux  Redux Thunk middleware allows you to write action creators that return a function instead of an action. The thunk can be used to delay the dispatch of an action, or to dispatch only if a certain condition is met. The inner function receives the store methods dispatch and getState as parameters.

Comments
  • Great answer. I had one other issue, cause I'm using 'composeWithDevTools(applyMiddleware(thunk, logger))'. So I just wrote my own interface 'export interface ThunkDispatchProp { dispatch: Dispatch<Action> & DispatchFunctionType }'. Then my components Prop interface doesn't extend 'DispatchProp', but 'ThunkDispatchProp'. Still feels like a hack a bit, but it works and if the next person looks at it he has a chance to figure out what's going on. Would be happy about your comment on it though.
  • And if you move the call to combineReducers out of this call (const rootReducer = combineReducers(stuff)), then you can find StateType as it is the return type of the rootReducer (type StateType = ResultType<typeof rootReducer>).