My action creators:
// file: redux/contest/actions.ts
import { ThunkAction } from 'redux-thunk'
import { ContestActionTypes, /* ... */ SET_CONTEST_CONFIG } from './types' ;
import { CONFIG_COLL, CONTEST_KEY, database } from '../../database'
import { RootState } from '../store';
/* ... */
export const setContestConfig: (arg0: IContestState) => ContestActionTypes =
(contestState) => ({ type: SET_CONTEST_CONFIG, payload: contestState })
export const loadContestConfig = (): ThunkAction<void, RootState, unknown, ContestActionTypes> =>
async dispatch => {
const data = await database.collection(CONFIG_COLL).doc(CONTEST_KEY).get()
dispatch(setContestConfig(data))
}
// file: redux/contest/types.ts
/* ... various action structures defined as interface ... */
export type ContestActionTypes = ISerialAction | IStringArrayAction | ITypeOnlyAction | IStringOnlyAction | ISetContestAction
This part compiles without any problems.
Now in my index.tsx I have this:
import React from 'react';
import ReactDOM from 'react-dom';
import { applyMiddleware, createStore } from 'redux'
import { Provider } from 'react-redux'
import thunk from 'redux-thunk'
import App from './App';
import { rootReducer } from './redux/store'
import { loadContestConfig, saveContestConfig } from './redux/contest/actions';
const store = createStore( rootReducer, applyMiddleware( thunk ) )
store.dispatch( loadContestConfig() ) // here I want to initialize state from the database
/* ... */
And on the line 11 of index.tsx ( store.dispatch(...)
) I get error message TS-2345
Argument of type 'ThunkAction<void, CombinedState<{ app: AppState; contest: IContestState; }>, unknown, ContestActionTypes>' is not assignable to parameter of type 'ISetStationAction | ISaveAppStateAction | ISerialAction | IStringArrayAction | ITypeOnlyAction | IStringOnlyAction | ISetContestAction'.
Type 'ThunkAction<void, CombinedState<{ app: AppState; contest: IContestState; }>, unknown, ContestActionTypes>' is missing the following properties from type 'ISetContestAction': type, payload TS2345
Of course, the action passed as to dispatch (in function loadContestConfig in the first file) has both type
and payload
, so I have no idea what's wrong here. I followed tutorials but this is incomprehensible, I just can't see the problem.
Finally, I was able to dig the solution. It is necessary to specify the type of dispatch
function because typescript is unable to determine the correct overload.
Solution highlights
in file ./redux/store.ts
(store declarations)
import { combineReducers } from 'redux'
import { ThunkDispatch } from 'redux-thunk'
import { AppActionTypes } from './station/types'
import { ContestActionTypes } from './contest/types'
import { stationReducer } from './station/reducers'
import { contestStateReducer } from './contest/reducers'
export const rootReducer = combineReducers({ station: stationReducer, contest: contestStateReducer })
export type RootState = ReturnType<typeof rootReducer>
export type StoreActionTypes = AppActionTypes | ContestActionTypes
// the following line is essential - we define proper function type for dispatch with thunk
export type DispatchFunctionType = ThunkDispatch<RootState, undefined, StoreActionTypes>
in file ./index.tsx
(React app main TSX file)
import React from 'react';
import ReactDOM from 'react-dom';
import { applyMiddleware, createStore} from 'redux'
import { Provider } from 'react-redux'
import thunk from 'redux-thunk'
import App from './App';
import { DispatchFunctionType, rootReducer, RootState } from './redux/store'
import { loadContestConfig } from './redux/contest/actions';
import { loadStation } from './redux/station/actions';
const store = createStore( rootReducer,
applyMiddleware<DispatchFunctionType, RootState>( thunk ) ) // <- this is essential
store.dispatch(loadContestConfig()) // here I had TS2345 before, now no more problems
store.dispatch(loadStation()) // - dtto -
The same dispatch
function type must be declared wherever dispatch
function is passed as parameter.
Example: in file StationDataModal.tsx
...
import { DispatchFunctionType, RootState } from "./redux/store"
...
// the following mapping function also caused TS-2345
// when dispatch type was not declared explicitly
const mapDispatchToProps = ( dispatch: DispatchFunctionType ) => {
return {
setContestName: ( name: string ) => {
dispatch(setContestName( name ))
dispatch(saveContestConfig())
},
setStationData: ( mycall: string, mywwloc: string ) => {
dispatch(setStation( { mycall, mywwloc } ))
dispatch(saveStation())
}
}
}
...
class StationDataModal extends React.Component<StationDataProps> {
/* component definition ... */
}
export default connect( mapStateToProps, mapDispatchToProps ) (StationDataModal)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.