MapDispatchToProps causes Typescript Error in parent-component, expecting Actions to be passed as props












2















In my child component I am defining MapDispatchToProps, pass them into connect and accordingly define an interface PropsFromDispatch that is extended in React.Component Props Interface. Now in my parent component Typescript is telling me that it is missing the properties that I defined in PropsFromDispatch.



This doesn't seem entirely absurd, as I am defining them as part of the React.Component Props interface, however I would expect 'connect' to take care of this the same way that it is taking care of my PropsFromState, which I also don't have to pass from parent to child component, but is mapped from the State to Props.



/JokeModal.tsx



...

interface Props extends PropsFromState, PropsFromDispatch {
isOpen: boolean
renderButton: boolean
}

...

const mapDispatchToProps = (dispatch: Dispatch<any>):
PropsFromDispatch => {
return {
tellJoke: (newJoke: INewJoke) => dispatch(tellJoke(newJoke)),
clearErrors: () => dispatch(clearErrors())
}
}

interface PropsFromDispatch {
tellJoke: (newJoke: INewJoke) => void
clearErrors: () => void
}

...

export default connect(mapStateToProps, mapDispatchToProps)(JokeModal);


/Parent.tsx



...

button = <JokeModal isOpen={false} renderButton={true} />
...


In this line of /Parent.tsx Typescript is now telling me:



Type '{ isOpen: false; renderButton: true; }' is missing the 
following properties from type 'Readonly<Pick<Props, "isOpen" |
"renderButton" | "tellJoke" | "clearErrors">>': tellJoke, clearErrors
ts(2739)


Interestingly I can avoid the error entirely by removing MapDispatchToProps and instead passing in the actions directly into connect(including dispatch already in the action creator):



export default connect(mapStateToProps, { tellJoke, clearErrors })(JokeModal);


Nevertheless I would like to know how to use MapDispatchToProps here and also why Typescript is expecting me to pass these actions to the child component?



Happy to hear your advice!










share|improve this question























  • What version are you using for react and @types/react?

    – CoderSpinoza
    Jan 2 at 6:09











  • @CoderSpinoza "react": "^16.6.3" and using "react-scripts-ts": "^4.0.8" from create-react-app and "typescript": "^3.2.1"

    – Leon vdb
    Jan 2 at 10:05











  • Are you sure you're not exporting and then importing the non-connected JokeModal component?

    – Yakimych
    Jan 9 at 15:27
















2















In my child component I am defining MapDispatchToProps, pass them into connect and accordingly define an interface PropsFromDispatch that is extended in React.Component Props Interface. Now in my parent component Typescript is telling me that it is missing the properties that I defined in PropsFromDispatch.



This doesn't seem entirely absurd, as I am defining them as part of the React.Component Props interface, however I would expect 'connect' to take care of this the same way that it is taking care of my PropsFromState, which I also don't have to pass from parent to child component, but is mapped from the State to Props.



/JokeModal.tsx



...

interface Props extends PropsFromState, PropsFromDispatch {
isOpen: boolean
renderButton: boolean
}

...

const mapDispatchToProps = (dispatch: Dispatch<any>):
PropsFromDispatch => {
return {
tellJoke: (newJoke: INewJoke) => dispatch(tellJoke(newJoke)),
clearErrors: () => dispatch(clearErrors())
}
}

interface PropsFromDispatch {
tellJoke: (newJoke: INewJoke) => void
clearErrors: () => void
}

...

export default connect(mapStateToProps, mapDispatchToProps)(JokeModal);


/Parent.tsx



...

button = <JokeModal isOpen={false} renderButton={true} />
...


In this line of /Parent.tsx Typescript is now telling me:



Type '{ isOpen: false; renderButton: true; }' is missing the 
following properties from type 'Readonly<Pick<Props, "isOpen" |
"renderButton" | "tellJoke" | "clearErrors">>': tellJoke, clearErrors
ts(2739)


Interestingly I can avoid the error entirely by removing MapDispatchToProps and instead passing in the actions directly into connect(including dispatch already in the action creator):



export default connect(mapStateToProps, { tellJoke, clearErrors })(JokeModal);


Nevertheless I would like to know how to use MapDispatchToProps here and also why Typescript is expecting me to pass these actions to the child component?



Happy to hear your advice!










share|improve this question























  • What version are you using for react and @types/react?

    – CoderSpinoza
    Jan 2 at 6:09











  • @CoderSpinoza "react": "^16.6.3" and using "react-scripts-ts": "^4.0.8" from create-react-app and "typescript": "^3.2.1"

    – Leon vdb
    Jan 2 at 10:05











  • Are you sure you're not exporting and then importing the non-connected JokeModal component?

    – Yakimych
    Jan 9 at 15:27














2












2








2








In my child component I am defining MapDispatchToProps, pass them into connect and accordingly define an interface PropsFromDispatch that is extended in React.Component Props Interface. Now in my parent component Typescript is telling me that it is missing the properties that I defined in PropsFromDispatch.



This doesn't seem entirely absurd, as I am defining them as part of the React.Component Props interface, however I would expect 'connect' to take care of this the same way that it is taking care of my PropsFromState, which I also don't have to pass from parent to child component, but is mapped from the State to Props.



/JokeModal.tsx



...

interface Props extends PropsFromState, PropsFromDispatch {
isOpen: boolean
renderButton: boolean
}

...

const mapDispatchToProps = (dispatch: Dispatch<any>):
PropsFromDispatch => {
return {
tellJoke: (newJoke: INewJoke) => dispatch(tellJoke(newJoke)),
clearErrors: () => dispatch(clearErrors())
}
}

interface PropsFromDispatch {
tellJoke: (newJoke: INewJoke) => void
clearErrors: () => void
}

...

export default connect(mapStateToProps, mapDispatchToProps)(JokeModal);


/Parent.tsx



...

button = <JokeModal isOpen={false} renderButton={true} />
...


In this line of /Parent.tsx Typescript is now telling me:



Type '{ isOpen: false; renderButton: true; }' is missing the 
following properties from type 'Readonly<Pick<Props, "isOpen" |
"renderButton" | "tellJoke" | "clearErrors">>': tellJoke, clearErrors
ts(2739)


Interestingly I can avoid the error entirely by removing MapDispatchToProps and instead passing in the actions directly into connect(including dispatch already in the action creator):



export default connect(mapStateToProps, { tellJoke, clearErrors })(JokeModal);


Nevertheless I would like to know how to use MapDispatchToProps here and also why Typescript is expecting me to pass these actions to the child component?



Happy to hear your advice!










share|improve this question














In my child component I am defining MapDispatchToProps, pass them into connect and accordingly define an interface PropsFromDispatch that is extended in React.Component Props Interface. Now in my parent component Typescript is telling me that it is missing the properties that I defined in PropsFromDispatch.



This doesn't seem entirely absurd, as I am defining them as part of the React.Component Props interface, however I would expect 'connect' to take care of this the same way that it is taking care of my PropsFromState, which I also don't have to pass from parent to child component, but is mapped from the State to Props.



/JokeModal.tsx



...

interface Props extends PropsFromState, PropsFromDispatch {
isOpen: boolean
renderButton: boolean
}

...

const mapDispatchToProps = (dispatch: Dispatch<any>):
PropsFromDispatch => {
return {
tellJoke: (newJoke: INewJoke) => dispatch(tellJoke(newJoke)),
clearErrors: () => dispatch(clearErrors())
}
}

interface PropsFromDispatch {
tellJoke: (newJoke: INewJoke) => void
clearErrors: () => void
}

...

export default connect(mapStateToProps, mapDispatchToProps)(JokeModal);


/Parent.tsx



...

button = <JokeModal isOpen={false} renderButton={true} />
...


In this line of /Parent.tsx Typescript is now telling me:



Type '{ isOpen: false; renderButton: true; }' is missing the 
following properties from type 'Readonly<Pick<Props, "isOpen" |
"renderButton" | "tellJoke" | "clearErrors">>': tellJoke, clearErrors
ts(2739)


Interestingly I can avoid the error entirely by removing MapDispatchToProps and instead passing in the actions directly into connect(including dispatch already in the action creator):



export default connect(mapStateToProps, { tellJoke, clearErrors })(JokeModal);


Nevertheless I would like to know how to use MapDispatchToProps here and also why Typescript is expecting me to pass these actions to the child component?



Happy to hear your advice!







reactjs typescript redux react-redux redux-thunk






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Jan 1 at 10:54









Leon vdbLeon vdb

182




182













  • What version are you using for react and @types/react?

    – CoderSpinoza
    Jan 2 at 6:09











  • @CoderSpinoza "react": "^16.6.3" and using "react-scripts-ts": "^4.0.8" from create-react-app and "typescript": "^3.2.1"

    – Leon vdb
    Jan 2 at 10:05











  • Are you sure you're not exporting and then importing the non-connected JokeModal component?

    – Yakimych
    Jan 9 at 15:27



















  • What version are you using for react and @types/react?

    – CoderSpinoza
    Jan 2 at 6:09











  • @CoderSpinoza "react": "^16.6.3" and using "react-scripts-ts": "^4.0.8" from create-react-app and "typescript": "^3.2.1"

    – Leon vdb
    Jan 2 at 10:05











  • Are you sure you're not exporting and then importing the non-connected JokeModal component?

    – Yakimych
    Jan 9 at 15:27

















What version are you using for react and @types/react?

– CoderSpinoza
Jan 2 at 6:09





What version are you using for react and @types/react?

– CoderSpinoza
Jan 2 at 6:09













@CoderSpinoza "react": "^16.6.3" and using "react-scripts-ts": "^4.0.8" from create-react-app and "typescript": "^3.2.1"

– Leon vdb
Jan 2 at 10:05





@CoderSpinoza "react": "^16.6.3" and using "react-scripts-ts": "^4.0.8" from create-react-app and "typescript": "^3.2.1"

– Leon vdb
Jan 2 at 10:05













Are you sure you're not exporting and then importing the non-connected JokeModal component?

– Yakimych
Jan 9 at 15:27





Are you sure you're not exporting and then importing the non-connected JokeModal component?

– Yakimych
Jan 9 at 15:27












1 Answer
1






active

oldest

votes


















1














I was able to reproduce your problem and the issue is apparently in the type signature of the mapDispatchToProps function in the source code, you can see that it has a type parameter Action = AnyAction



export interface Dispatch<A extends Action = AnyAction> {
<T extends A>(action: T): T
}


The solution to your problem is to change Dispatch<any> to Dispatch<AnyAction>:



const mapDispatchToProps = (dispatch: Dispatch<AnyAction>): PropsFromDispatch


Note that since you're using redux-thunk, the type system might not allow you to call dispatch on a thunk, so you might have to either cheat by calling



clearErrors: () => dispatch<any>(clearErrors());


or use rather verbose typing with ThunkDispatch and ThunkAction. I have an example of such a typing here: ThunkDispatch and the corresponding ThunkAction. Note that I use typesafe-actions.






share|improve this answer

























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53994860%2fmapdispatchtoprops-causes-typescript-error-in-parent-component-expecting-action%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    I was able to reproduce your problem and the issue is apparently in the type signature of the mapDispatchToProps function in the source code, you can see that it has a type parameter Action = AnyAction



    export interface Dispatch<A extends Action = AnyAction> {
    <T extends A>(action: T): T
    }


    The solution to your problem is to change Dispatch<any> to Dispatch<AnyAction>:



    const mapDispatchToProps = (dispatch: Dispatch<AnyAction>): PropsFromDispatch


    Note that since you're using redux-thunk, the type system might not allow you to call dispatch on a thunk, so you might have to either cheat by calling



    clearErrors: () => dispatch<any>(clearErrors());


    or use rather verbose typing with ThunkDispatch and ThunkAction. I have an example of such a typing here: ThunkDispatch and the corresponding ThunkAction. Note that I use typesafe-actions.






    share|improve this answer






























      1














      I was able to reproduce your problem and the issue is apparently in the type signature of the mapDispatchToProps function in the source code, you can see that it has a type parameter Action = AnyAction



      export interface Dispatch<A extends Action = AnyAction> {
      <T extends A>(action: T): T
      }


      The solution to your problem is to change Dispatch<any> to Dispatch<AnyAction>:



      const mapDispatchToProps = (dispatch: Dispatch<AnyAction>): PropsFromDispatch


      Note that since you're using redux-thunk, the type system might not allow you to call dispatch on a thunk, so you might have to either cheat by calling



      clearErrors: () => dispatch<any>(clearErrors());


      or use rather verbose typing with ThunkDispatch and ThunkAction. I have an example of such a typing here: ThunkDispatch and the corresponding ThunkAction. Note that I use typesafe-actions.






      share|improve this answer




























        1












        1








        1







        I was able to reproduce your problem and the issue is apparently in the type signature of the mapDispatchToProps function in the source code, you can see that it has a type parameter Action = AnyAction



        export interface Dispatch<A extends Action = AnyAction> {
        <T extends A>(action: T): T
        }


        The solution to your problem is to change Dispatch<any> to Dispatch<AnyAction>:



        const mapDispatchToProps = (dispatch: Dispatch<AnyAction>): PropsFromDispatch


        Note that since you're using redux-thunk, the type system might not allow you to call dispatch on a thunk, so you might have to either cheat by calling



        clearErrors: () => dispatch<any>(clearErrors());


        or use rather verbose typing with ThunkDispatch and ThunkAction. I have an example of such a typing here: ThunkDispatch and the corresponding ThunkAction. Note that I use typesafe-actions.






        share|improve this answer















        I was able to reproduce your problem and the issue is apparently in the type signature of the mapDispatchToProps function in the source code, you can see that it has a type parameter Action = AnyAction



        export interface Dispatch<A extends Action = AnyAction> {
        <T extends A>(action: T): T
        }


        The solution to your problem is to change Dispatch<any> to Dispatch<AnyAction>:



        const mapDispatchToProps = (dispatch: Dispatch<AnyAction>): PropsFromDispatch


        Note that since you're using redux-thunk, the type system might not allow you to call dispatch on a thunk, so you might have to either cheat by calling



        clearErrors: () => dispatch<any>(clearErrors());


        or use rather verbose typing with ThunkDispatch and ThunkAction. I have an example of such a typing here: ThunkDispatch and the corresponding ThunkAction. Note that I use typesafe-actions.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Jan 11 at 11:24

























        answered Jan 11 at 10:37









        YakimychYakimych

        15.4k64463




        15.4k64463
































            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53994860%2fmapdispatchtoprops-causes-typescript-error-in-parent-component-expecting-action%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            MongoDB - Not Authorized To Execute Command

            How to fix TextFormField cause rebuild widget in Flutter

            in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith