MapDispatchToProps 导致父组件中的 Typescript 错误,期望操作作为道具传递 [英] MapDispatchToProps causes Typescript Error in parent-component, expecting Actions to be passed as props

查看:16
本文介绍了MapDispatchToProps 导致父组件中的 Typescript 错误,期望操作作为道具传递的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的子组件中,我定义了 MapDispatchToProps,将它们传递给 connect 并相应地定义了一个接口 PropsFromDispatch,该接口在 React.Component Props 接口中扩展.现在在我的父组件中,Typescript 告诉我它缺少我在 PropsFromDispatch 中定义的属性.

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.

这似乎并不完全荒谬,因为我将它们定义为 React.Component Props 接口的一部分,但是我希望connect"能够像处理我的 PropsFromState 一样处理这个问题,我也不必从父组件传递到子组件,而是从状态映射到道具.

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

/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

/Parent.tsx

...

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

在/Parent.tsx 的这一行中,Typescript 现在告诉我:

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)

有趣的是,我可以通过删除 MapDispatchToProps 来完全避免错误,而是将动作直接传递到连接中(包括动作创建者中已经存在的调度):

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);

不过我想知道如何在这里使用 MapDispatchToProps 以及为什么 Typescript 期望我将这些操作传递给子组件?

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?

很高兴听到您的建议!

推荐答案

我能够重现您的问题,问题显然出在 mapDispatchToProps 函数的类型签名中"https://github.com/reduxjs/redux/blob/32ac7e64bf548e0287807fae9e622aa9c55ff065/index.d.ts#L121" rel="noreferrer">源码,可以看到它有一个类型参数Action = AnyAction

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
}

解决你的问题的方法是将Dispatch改为Dispatch:

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

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

请注意,由于您使用的是 redux-thunk,类型系统可能不允许您在 thunk 上调用 dispatch,因此您可能不得不通过调用来欺骗

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());

或者使用 ThunkDispatchThunkAction 使用相当冗长的输入.我在这里有一个这样打字的例子:ThunkDispatch 和相应的 ThunkAction.请注意,我使用 typesafe-actions.

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.

这篇关于MapDispatchToProps 导致父组件中的 Typescript 错误,期望操作作为道具传递的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆