2016-05-03 27 views
6

Sto cercando di usare react-redux con dattiloscritto e sto ricevendo un errore di tipo quando provo a iniettare oggetti di scena usando connect() e mapStateToProps.Errore di tipo quando si usa Typescript con React-Redux

La mia componente si presenta così:

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

Il negozio si presenta così

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

Infine, ho definito i miei tipi di essere:

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

interface HelloState { 
    counter:number; 
} 

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

Quando provo e compila il codice ottengo il seguente errore:

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

È interessante notare che il codice funziona anche se genera l'errore di tipo. Inoltre, la modifica dell'interfaccia prop del componente in qualsiasi soluzione risolve anche il problema. Sembra che il sistema di tipi non capisca che i due oggetti sono uniti dalle due funzioni mappate.

risposta

7

Ho trovato la risposta nel penultimo post su questo Github issue. Senza il parametro type su mapStateToProps e/o mapDispatchToProps o su connect, verrà generata un'intersezione dei tipi di ritorno delle due funzioni della mappa.

+0

hai scoperto qualcosa di più (spiegazione) su questo? Ho notato che non hai ricevuto alcuna risposta sulla tua domanda sul problema github. Stai usando tipi di ritorno per mapStateToProps e mapDispatchToProps (per i quali probabilmente dovevi rendere facoltativi i membri dell'interfaccia)? È così che attualmente lo sto applicando per essere in grado di funzionare. – Jeroen

+1

Sì, ho specificato i tipi di ritorno su mapStateToProps e mapDispatchToProps. I membri dell'interfaccia devono essere facoltativi, a prescindere da ciò che altrimenti fallirà dove viene chiamato il componente. Non sono un grande fan di come TS funziona con Redux e react-redux, ma non riesco a pensare ad un buon modo per farlo adesso. – Ochowie

26

Per preservare la sicurezza di tipo è possibile dividere i vostri oggetti di scena in alcune parti, un responsabile di puntelli normali e uno per gli spedizionieri:

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

Per coloro che cercano soluzione rapida: basta aggiungere 'come qualsiasi' al componente di base .

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

Nel mio caso, non avevo alcun valore per 'mapDispatchToProps', quindi passare esplicitamente' null' o 'undefined' invece di lasciare il valore sembrava far sparire l'errore:' export default connect (mapStateToProps, null) (MyComponent); ' – Shepmaster

+0

come. come? come! \\ (^ o ^)/ – Raffael

+0

Questo fallisce in modo specifico in quanto è necessario digitare parameterize connect: Anche in questo caso, sembra che ci siano problemi più profondi con la connessione. – stevematdavies

Problemi correlati