2016-05-03 7 views
6

Ich versuche, react-Redux mit Typoskript zu verwenden, und ich bekomme einen Typfehler, wenn ich versuche, Requisiten mit Hilfe von connect() und mapStateToProps zu injizieren.Typ Fehler bei der Verwendung von Typescript mit React-Redux

Meine Komponente wie folgt aussieht:

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

Der Laden wie diesem Schließlich

let store = createStore(
    (state:HelloState, action:HelloAction) => { 
     switch (action.type) { 
      case 'INCR': 
       return {counter: state.counter + action.by}; 
      default: 
       return state; 
     } 
    }, 

sieht, habe ich meine Typen definiert werden:

interface HelloProps { 
    counter?: number; 
    incr?:() => any; 
    decr?:() => any; 
} 

interface HelloState { 
    counter:number; 
} 

interface HelloAction { 
    type:string, 
    by:number; 
} 

Wenn ich versuche, und Kompiliere den Code Ich erhalte den folgenden Fehler:

(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>' 

Interessanterweise funktioniert der Code immer noch, obwohl es den Typfehler auslöst. Auch das Ändern der Prop-Schnittstelle der Komponente in eine beliebige Komponente löst das Problem. Es scheint, als ob das Typsystem nicht versteht, dass die beiden Objekte durch die beiden abgebildeten Funktionen zusammengeführt werden.

Antwort

7

Ich fand die Antwort im vorletzten Beitrag auf diesem Github issue. Ohne den Typparameter sowohl mapStateToProps und/oder mapDispatchToProps als auch connect wird ein Schnittpunkt der Rückgabetypen der beiden Kartenfunktionen erzeugt.

+0

Haben Sie mehr darüber herausgefunden? Ich habe festgestellt, dass Sie auf Ihre Frage zum GitHub-Problem keine Antwort erhalten haben. Verwenden Sie Rückgabetypen für mapStateToProps und mapDispatchToProps (für die Sie wahrscheinlich die Mitglieder der Schnittstelle wie von Ihnen vorgeschlagen freigestellt haben mussten)? Das ist, wie ich es derzeit anwende, um laufen zu können. – Jeroen

+1

Ja, ich habe die Rückgabetypen für mapStateToProps und mapDispatchToProps angegeben. Die Schnittstellenelemente müssen optional sein, unabhängig davon, was sonst fehlschlägt, wenn die Komponente aufgerufen wird. Ich bin kein großer Fan davon, wie TS mit Redux und der connect-Methode von react-redux arbeitet, aber ich kann mir im Moment keine gute Lösung vorstellen. – Ochowie

26

Um Typsicherheit zu bewahren Sie Ihre Requisiten in Teile aufteilen kann, eine für normale Requisiten und eine für Disponenten:

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

Für diejenigen, die für eine schnelle Abhilfe zu suchen: fügen Sie einfach ‚wie jeder‘ zu Basiskomponente .

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

In meinem Fall hatte ich keine Werte für 'mapDispatchToProps'. Wenn also' null' oder 'undefined' explizit übergeben wurde, anstatt den Wert zu belassen, schien der Fehler zu verschwinden:' export default connect (mapStateToProps, null) (MyComponent); ' – Shepmaster

+0

als. wie? wie! \\ (^ o ^)/ – Raffael

+0

Dies schlägt speziell fehl, da Sie connect eingeben müssen: Selbst dann scheint es tiefer Probleme mit connect zu geben. – stevematdavies

Verwandte Themen