Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to dispatch ThunkAction with redux-thunk and TypeScript

I am having trouble with dispatching a redux-thunk action using Typescript.

import { AnyAction, applyMiddleware, createStore } from 'redux'
import thunk, { ThunkAction } from 'redux-thunk'

interface State {
  counter: number
}

const initialState: State = {
  counter: 10
}

function reducer(state = initialState, action: AnyAction) {
  switch (action.type) {
    case 'increment':
      return { counter: action.payload }
    default:
      return state
  }
}

function increment(): ThunkAction<void, State, unknown, AnyAction> {
  return async function (dispatch) {
    dispatch({
      type: 'increment',
      payload: 20
    })
  }
}

const store = createStore(reducer, applyMiddleware(thunk))

store.dispatch(increment())

This is the error that I receive:

Argument of type 'ThunkAction<void, State, unknown, AnyAction>' is not assignable to parameter of type 'AnyAction'.
  Property 'type' is missing in type 'ThunkAction<void, State, unknown, AnyAction>' but required in type 'AnyAction'.

I have tried multiple different thinkgs for action type such as custom interface, Action etc. and nothing works.

like image 929
jm18457 Avatar asked Jan 25 '23 15:01

jm18457


1 Answers

The default dispatch type does not know of thunk, as the "base redux" types are not very powerful. So you'll have to cast it to ThunkDispatch manually:

(store.dispatch as ThunkDispatch<State, unknown, AnyAction>)(increment())

Just as a PSA: The type of redux you are writing here (vanilla redux with hand-written actions, action-types, switch-case statements and immutable logic in reducers) is no longer the "officially recommended approach" of writing redux. Please take a look at redux toolkit and best follow the official, up-to-date redux tutorials, as you are most likely following a very outdated one.

Redux Toolkit is also a lot easier to use in general, and specially with TypeScript (and store.dispatch will have the correct type if you use it ;) )

like image 103
phry Avatar answered Mar 07 '23 08:03

phry