2015-09-30 18 views
17

Sto utilizzando React.js con TypeScript. C'è un modo per creare componenti React che ereditano da altri componenti ma hanno alcuni oggetti/stati aggiuntivi?Estendere componenti React in TypeScript

Quello che sto cercando di realizzare è qualcosa di simile:

interface BaseStates { 
    a: number; 
} 

class GenericBase<S extends BaseStates> extends React.Component<void, S> { 
    protected getBaseInitialState(): BaseStates { 
     return { a: 3 }; 
    } 
} 

class Base extends GenericBase<BaseStates> { 
    getInitialState(): BaseStates { 
     return super.getBaseInitialState(); 
    } 
} 

interface DerivedStates extends BaseStates { 
    b: number; 
} 

class Derived extends GenericBase<DerivedStates> { 
    getInitialState(): DerivedStates { 
     var initialStates = super.getBaseInitialState() as DerivedStates; // unsafe?? 
     initialStates.b = 4; 
     return initialStates 
    } 
} 

Tuttavia, questa fallirà se chiamo this.setState in Derived, ricevo un errore tipografico (parametro di tipo DerivedStates non è cedibile a digitare S). Suppongo che questa non sia una cosa specifica per TypeScript, ma una limitazione generale del mixaggio dell'ereditarietà con i generici (?). C'è qualche soluzione alternativa sicura per questo?

UPDATE

La soluzione che ho optato per (in base alla risposta di David Sherret):

interface BaseStates { 
    a: number; 
} 

class GenericBase<S extends BaseStates> extends React.Component<void, S> { 
    constructor() { 
     super(); 
     this.state = this.getInitialState(); 
    } 

    getInitialState(): S { 
     return { a: 3 } as S; 
    } 

    update() { 
     this.setState({ a: 7 } as S); 
    } 
} 

interface DerivedStates extends BaseStates { 
    b: number; 
} 

class Derived extends GenericBase<DerivedStates> { 
    getInitialState(): DerivedStates { 
     var initialStates = super.getInitialState(); 
     initialStates.b = 4; 
     return initialStates; 
    } 

    update() { 
     this.setState({ a: 7, b: 4 }); 
    } 
} 

risposta

10

È possibile impostare solo alcune proprietà dello stato in una sola volta in Derived utilizzando un tipo di asserzione:

this.setState({ b: 4 } as DerivedStates); // do this 
this.setState({ a: 7 } as DerivedStates); // or this 
this.setState({ a: 7, b: 4 });   // or this 

Tra l'altro, non c'è bisogno di avere nomi diversi per getInitialState ... si può solo fare:

class GenericBase<S extends BaseStates> extends React.Component<void, S> { 
    constructor() { 
     super();   
     this.state = this.getInitialState(); 
    } 

    protected getInitialState() { 
     return { a: 3 } as BaseStates as S; 
    } 
} 

class Derived extends GenericBase<DerivedStates> { 
    getInitialState() { 
     var initialStates = super.getInitialState(); 
     initialStates.b = 4; 
     return initialStates; 
    } 
} 
+0

Grazie per la risposta rapida. Per la tua soluzione, ottengo un errore per la seconda riga del costruttore: 'type 'BaseStates' non è assegnabile al tipo 'S'' che non è sorprendente, poiché' S' è una sottoclasse di 'BaseStates'. . – Thegaram

+0

@ Thegaram lo stavo solo aggiustando. Risolto ora. –

+0

Grazie! Ancora non sono sicuro di quanto siano sicuri questi downcast, ma alla mia domanda viene data una risposta. – Thegaram

Problemi correlati