将 Typescript 与 React-Redux 一起使用时出现类型错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37010193/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Type Error when using Typescript with React-Redux
提问by Ochowie
I am trying to use react-redux with typescript and I'm getting a type error when I try to inject props using connect() and mapStateToProps.
我正在尝试将 react-redux 与 typescript 一起使用,当我尝试使用 connect() 和 mapStateToProps 注入道具时出现类型错误。
My component looks like this:
我的组件如下所示:
function mapStateToProps(state) {
return {
counter: state.counter
};
}
function mapDispatchToProps(dispatch) {
return {
incr: () => {
dispatch({type: 'INCR', by: 2});
},
decr: () => {
dispatch({type: 'INCR', by: -1});
}
};
}
export default class Counter extends React.Component<HelloProps, any> {
render() {
return (
<div>
<p>
<label>Counter: </label>
<b>#{this.props.counter}</b>
</p>
<button onClick={e => this.props.incr() }>INCREMENT</button>
<span style={{ padding: "0 5px" }}/>
<button onClick={e => this.props.decr() }>DECREMENT</button>
);
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Counter);
The store looks like this
这家店长这个样子
let store = createStore(
(state:HelloState, action:HelloAction) => {
switch (action.type) {
case 'INCR':
return {counter: state.counter + action.by};
default:
return state;
}
},
Finally, I have defined my types to be:
最后,我将我的类型定义为:
interface HelloProps {
counter?: number;
incr?: () => any;
decr?: () => any;
}
interface HelloState {
counter:number;
}
interface HelloAction {
type:string,
by:number;
}
When I try and compile the code I get the following error:
当我尝试编译代码时,出现以下错误:
(39,61): error TS2345: Argument of type 'typeof Counter' is not assignable to parameter of type 'ComponentClass<{ counter: any; } & { incr: () => void; decr: () => void; }> | StatelessComponent<...'.
Type 'typeof Counter' is not assignable to type 'StatelessComponent<{ counter: any; } & { incr: () => void; decr: () => void; }>'.
Type 'typeof Counter' provides no match for the signature '(props?: { counter: any; } & { incr: () => void; decr: () => void; }, context?: any): ReactElement<any>'
Interestingly the code still works even though it throws the type error. Also, changing the component's prop interface to any also solves the issue. It seems like the type system doesn't understand that the two objects are merged by the two mapped functions.
有趣的是,即使抛出类型错误,代码仍然有效。此外,将组件的 prop 接口更改为 any 也可以解决该问题。似乎类型系统不明白这两个对象是由两个映射函数合并的。
采纳答案by Ochowie
I found the answer in the second to last post on this Github issue. Without the type parameter on both the mapStateToProps
and/or mapDispatchToProps
or on connect
it will produce an intersection of the return types of the two map functions.
我在这个 Github问题的倒数第二个帖子中找到了答案。如果没有mapStateToProps
和/或mapDispatchToProps
或connect
它的类型参数将产生两个映射函数的返回类型的交集。
回答by vinga
To preserve type safety you can divide your props in parts, one responsible for normal props and one for dispatchers:
为了保持类型安全,你可以将你的 props 分成几部分,一个负责普通 props,一个负责调度员:
import * as React from 'react';
import {connect} from 'react-redux';
interface StateProps {
textPros: string,
optionalText?: string,
}
interface DispatchProps {
onClick1: Function,
}
class MyComp extends React.Component<StateProps & DispatchProps , any> {
render() {
return (<div onClick={this.props.onClick1}>{this.props.textPros}</div>);
}
}
const mapStateToProps = (state: any, ownProp? :any):StateProps => ({
textPros: "example text",
});
const mapDispatchToProps = (dispatch: any):DispatchProps => ({
onClick1: () => {
dispatch({ type: 'CLICK_ACTION'});
}
});
export default connect(mapStateToProps, mapDispatchToProps)(MyComp);
For those who search for quick workaround: just add 'as any' to base component.
对于那些寻求快速解决方法的人:只需将“as any”添加到基本组件即可。
export default connect(mapStateToProps, mapDispatchToProps)(MyComp as any);