将 Typescript 与 React-Redux 结合使用时出现类型错误
Type Error when using Typescript with React-Redux
我正在尝试将 react-redux 与 typescript 一起使用,但当我尝试使用 connect() 和 mapStateToProps 注入 props 时出现类型错误。
我的组件如下所示:
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);
店铺长这样
let store = createStore(
(state:HelloState, action:HelloAction) => {
switch (action.type) {
case 'INCR':
return {counter: state.counter + action.by};
default:
return state;
}
},
最后,我将我的类型定义为:
interface HelloProps {
counter?: number;
incr?: () => any;
decr?: () => any;
}
interface HelloState {
counter:number;
}
interface HelloAction {
type:string,
by:number;
}
当我尝试编译代码时出现以下错误:
(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>'
有趣的是,即使抛出类型错误,代码仍然有效。此外,将组件的 prop 接口更改为 any 也可以解决问题。似乎类型系统不理解这两个对象是由两个映射函数合并的。
我在这个 Github issue 的倒数第二个 post 中找到了答案。 mapStateToProps
and/or mapDispatchToProps
或 connect
上都没有类型参数,它将产生两个映射函数的 return 类型的交集。
为了保持类型安全,您可以将道具分成几部分,一份负责普通道具,一份负责调度程序:
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);
对于那些寻找快速解决方法的人:只需将 'as any' 添加到基本组件。
export default connect(mapStateToProps, mapDispatchToProps)(MyComp as any);
我正在尝试将 react-redux 与 typescript 一起使用,但当我尝试使用 connect() 和 mapStateToProps 注入 props 时出现类型错误。
我的组件如下所示:
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);
店铺长这样
let store = createStore(
(state:HelloState, action:HelloAction) => {
switch (action.type) {
case 'INCR':
return {counter: state.counter + action.by};
default:
return state;
}
},
最后,我将我的类型定义为:
interface HelloProps {
counter?: number;
incr?: () => any;
decr?: () => any;
}
interface HelloState {
counter:number;
}
interface HelloAction {
type:string,
by:number;
}
当我尝试编译代码时出现以下错误:
(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>'
有趣的是,即使抛出类型错误,代码仍然有效。此外,将组件的 prop 接口更改为 any 也可以解决问题。似乎类型系统不理解这两个对象是由两个映射函数合并的。
我在这个 Github issue 的倒数第二个 post 中找到了答案。 mapStateToProps
and/or mapDispatchToProps
或 connect
上都没有类型参数,它将产生两个映射函数的 return 类型的交集。
为了保持类型安全,您可以将道具分成几部分,一份负责普通道具,一份负责调度程序:
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);
对于那些寻找快速解决方法的人:只需将 'as any' 添加到基本组件。
export default connect(mapStateToProps, mapDispatchToProps)(MyComp as any);