react-redux-typescript-guide: Incorrect action creator type when using bindActionCreators and redux-thunk
Specifically I have this action defined.
getTransitionForm: (params: GetTransitionFormParams) =>
(dispatch: Dispatch<RootState>, getState: () => RootState, extraArgument: any) =>
Promise<any>;
When mapped as follows as per your guide from section “Connected Container without OwnProps using Type Inference” https://github.com/piotrwitek/react-redux-typescript-guide#connected-container-with-ownprops
export const mapDispatchToProps = (dispatch: Dispatch<RootState>) =>
bindActionCreators(
{
getTransitionForm,
},
dispatch
);
const dispatchProps = returntypeof(mapDispatchToProps);
The resulting value of dispatchProps is
const dispatchProps: {
getTransitionForm: (params: GetTransitionFormParams) =>
(dispatch: Dispatch<RootState>, getState: () => RootState, extraArgument: any) =>
Promise<any>;
}
I believe after binding it should be.
const dispatchProps: {
getTransitionForm: (params: GetTransitionFormParams) => Promise<any>;
}
Which I expect is not going to be easy to derive. I only discovered this as I wanted to do something with the returned promise. Thanks for your great guide.
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Comments: 15 (5 by maintainers)
Commits related to this issue
- closes #6 — committed to piotrwitek/react-redux-typescript-guide by piotrwitek 7 years ago
- improved redux section text and examples (#36) * improved redux section text and examples updated tslint to strict for 2.6 and future new strict features * review fixes * updated deps * c... — committed to piotrwitek/react-redux-typescript-guide by piotrwitek 7 years ago
If people are still looking at how to get the correct typings for
bindActionCreators
when passing in ThunkActions, I’ve got an open PR to fix this, specifically the line: https://github.com/reduxjs/redux-thunk/pull/224/files#diff-b52768974e6bc0faccb7d4b75b162c99R31Overloading the function definition and conditionally returning a different object type if the action passed is of type
ThunkAction
:Let me know if it fits your needs
@rluiten this time I have thoroughly investigated and I found you are right, types are not correct but only for the thunk action creators. Specifically bindActionCreators could have been augmented by redux-thunk to fix that behaviour.
The types returned from connect should have bound action creators, but it seems they are still typed as thunk action creators so dispatch is not correctly applied.
When I changed mapDispatchToProps declaration to not use
bindActionCreators
it’s fixed, you can try: const mapDispatchToProps = (dispatch: Dispatch) => ({ updateRegion: (payload: RegionModel) => dispatch(SitesReducer.updateRegion(payload)), });The second one works because this time dispatch is correctly augmented by
redux-thunk
typings.The necessary fix is to augment
bindActionCreators
to apply augmented dispatch that can handle thunk actions, but it’s not possible with current Type Inference limitations.Sorry for the delay responding. It’s been a while since I looked at this, but I’ll get the conversation started with what I have and see if that’s helpful. I’m not totally sure if my code will directly translate, but hopefully, it will be helpful.
For reference,
ReturnType<typeof mapDispatchToProps>
is:The utility types involved are:
Hopefully, that helps. Let me know if there are any questions, and I’ll try to answer them.
I freely admit I might have flubbed something. But it compiles with no errors and appears to work (but that might be pure fluke).
Definition of my Component and its properties.
Inside my components member functions the type of 'props.getTransitionForm` appears to be. (conveniently visible in VSCode but I did not assume VSCode was correct) I am calling the action from a submit() function that is part of redux-form.
The fire*Action() functions are just examples.
I setup a test and i can use
await
it compiles with no errors, and appears to work correctly.If I use .then() I get a compile error.
The
getResult
above gives me the compile error where i try to use .then().TS2339: Property 'then' does not exist on type 'ThunkAction<Promise<any>, RootState, any>'.
This leads me to believe the types are not really correct, I am not implying they are easy to fix or can be fixed, I fudged the type for myself for now. It appears await isn’t enforcing type constraints equivalently to
.then()
, and since the underlying value is actually a promiseawait
works anyway.Currently i am just casting the property action to any to call then and all seems well with the world.
Thanks for your response, I raised this more to see if it rings a bell with you that might point out something I had missed or possibly even something you can address. I think its complex enough some sort of fix might not be easy and may require much deeper type knowledge than I have, or even typescript may not be able to do express the constraint in its current version.
Thanks,