将 Typescript 与 React-Redux 一起使用时出现类型错误

Posted

技术标签:

【中文标题】将 Typescript 与 React-Redux 一起使用时出现类型错误【英文标题】:Type Error when using Typescript with React-Redux 【发布时间】:2016-08-28 20:33:12 【问题描述】:

我正在尝试将 react-redux 与 typescript 一起使用,当我尝试使用 connect() 和 mapStateToProps 注入道具时出现类型错误。

我的组件如下所示:

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 也可以解决问题。似乎类型系统不理解这两个对象是由两个映射函数合并的。

【问题讨论】:

您将 Counter 组件导出两次,这可能也是这里的问题。 【参考方案1】:

我在这个 Github issue 的倒数第二个帖子中找到了答案。如果mapStateToProps 和/或mapDispatchToPropsconnect 上没有类型参数,它将产生两个映射函数的返回类型的交集。

【讨论】:

你有没有发现更多关于这个的(解释)?我注意到您在 github 问题上的问题没有收到任何答案。您是否使用 mapStateToProps 和 mapDispatchToProps 的返回类型(您可能必须按照您的建议将接口的成员设为可选)?这就是我目前应用它以使其能够运行的方式。 是的,我在 mapStateToProps 和 mapDispatchToProps 上指定了返回类型。接口成员必须是可选的,否则它会在调用组件时失败。我不太喜欢 TS 如何与 Redux 和 react-redux 的 connect 方法一起工作,但我现在想不出一个好的方法。【参考方案2】:

为了保持类型安全,你可以将你的 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);

对于那些寻求快速解决方法的人:只需将“as any”添加到基本组件即可。

export default connect(mapStateToProps, mapDispatchToProps)(MyComp as any);

【讨论】:

在我的情况下,我没有任何 mapDispatchToProps 的值,因此明确传递 nullundefined 而不是离开值似乎使错误消失:@987654326 @ 作为。作为?作为! \(^o^)/ 这特别失败,因为您需要对连接进行类型参数化:即使那样,连接似乎也存在更深层次的问题。 使用 TypeScript 然后在这里和那里放 any 有什么意义?不好的例子。

以上是关于将 Typescript 与 React-Redux 一起使用时出现类型错误的主要内容,如果未能解决你的问题,请参考以下文章

将 Nodejs 与 Typescript 一起使用

将 typescript 与 Babel 7 Standalone 一起使用

如何将命名空间与 TypeScript 外部模块一起使用?

Angularjs + Typescript,如何将 $routeParams 与 IRouteParamsService 一起使用

将 useRef 与 TypeScript 一起使用的问题

将 TypeScript 枚举与猫鼬模式一起使用