web-dev-qa-db-ja.com

TypeScriptをReact-Reduxで使用するとタイプエラーが発生する

TypeScriptでreact-reduxを使用しようとしていますが、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>' 

興味深いことに、タイプエラーがスローされても、コードは機能します。また、コンポーネントのプロップインターフェイスをanyに変更すると、問題も解決します。型システムは、2つのオブジェクトが2つのマップされた関数によってマージされていることを理解していないようです。

10
Ochowie

このGithubの最後から2番目の投稿で答えを見つけました issuemapStateToPropsおよび/またはmapDispatchToPropsまたはconnectの両方にtypeパラメーターがないと、2つのマップ関数の戻り値の型の共通部分が生成されます。

8
Ochowie

タイプの安全性を維持するために、小道具をパーツに分割できます。1つは通常の小道具を担当し、もう1つはディスパッチャーを担当します。

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

迅速な回避策を探している人のために:ベースコンポーネントに「asany」を追加するだけです。

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