2015-10-13 5 views
8

Diciamo che ho una classe di base con alcuni DataItems di proprietà che è matrice di DataItem:Ottenere tipo di una variabile e creare nuova istanza di questo tipo

export class BaseClass{ 
    dataItems:DataItems[]; 
} 

allora ho diverse classi che estendono BaseClass e le loro DataItems proprietà è un array di una classe che si estende DataItems:

export class BetterClass extends BaseClass{ 
    dataItems:BetterDataItems[]; 
} 

export class BestClass extends BaseClass{ 
    dataItems:BestDataItems[]; 
} 

Ora voglio aggiungere un metodo in BaseClass che crea DataItems e li aggiunge alla gamma. Sarebbe possibile fare tutto questo in BaseClass? Ho bisogno di creare un'istanza di BetterDataItems o BestDataItems, a seconda della classe utilizzata.

Al momento ho semplicemente aggiunto:

dataItemType: typeof DataItem; 

proprietà BaseClass e in ogni BaseClass classe che estende sovrascrivo questa variabile con il corretto tipo di elemento di dati:

in BetterClass:

dataItemType: typeof BetterDataItem = BetterDataItem; 

in BestClass:

dataItemType: typeof BestDataItem = BestDataItem; 

E poi, in BaseClass faccio questo:

var dataItem = new this.dataItemType(); 

Questo funziona bene, ma la mia domanda è - sarebbe possibile per evitare di avere dataItemType proprietà a tutti? Posso trovare un tipo di array dataItems e quindi creare una nuova istanza?

Grazie!

risposta

4

dattiloscritto Codice 1.6:

class DataItems { 

} 

class BaseClass { 
    dataItems:DataItems[]; 
    dataItemType: typeof DataItems = DataItems; 
} 

compila a:

var DataItems = (function() { 
    function DataItems() { 
    } 
    return DataItems; 
})(); 
var BaseClass = (function() { 
    function BaseClass() { 
     this.dataItemType = DataItems; 
    } 
    return BaseClass; 
})(); 

E si può vedere che le informazioni sul tipo per dataItems proprietà si perde nella BaseClass. Ecco come funziona il compilatore TypeScript. It does not support runtime checking. Quindi la risposta alla tua domanda è no.


vostra soluzione con dataItemType: typeof BetterDataItem = BetterDataItem; opere perché si rendono il compilatore dattiloscritto di aggiungere il comando JS: this.dataItemType = BetterDataItem; che può essere utilizzato in seguito.

4

Opzione 1: Si potrebbe eseguire l'override del metodo in ogni classe sub ...

export class BaseClass{ 
    dataItems:DataItem[]; 

    create() { 
     this.dataItems.push(new DataItem()); 
    } 
} 

export class BetterClass extends BaseClass{ 
    dataItems:BetterDataItem[]; 

    create() { 
     this.dataItems.push(new BetterDataItem()); 
    } 
} 

export class BestClass extends BaseClass{ 
    dataItems:BestDataItem[]; 

     create() { 
     this.dataItems.push(new BestDataItem()); 
    } 
} 

Opzione 2: Ma se si introduce una classe base generica, è possibile rimuovere la necessità di definire le proprietà DataItems su ogni classe e anche creare diverse istanze.

type MyT = typeof DataItem; 

export class GenericBaseClass<T extends DataItem> { 
    dataItems:T[]; 

    constructor(private dataType: MyT) { 

    } 

    create() { 
     this.dataItems.push(<T>new this.dataType()) 
    } 

} 

export class BaseClass extends GenericBaseClass<DataItem> { 
    constructor() { 
     super(DataItem); 
    } 
} 

export class BetterClass extends GenericBaseClass<DataItem> { 
    constructor() { 
     super(BetterDataItem); 
    } 
} 

export class BestClass extends GenericBaseClass<DataItem> { 
    constructor() { 
     super(BestDataItem); 
    } 
} 
+1

+1; Per completezza, penso che tu possa usare l'operatore 'instanceof' in' BaseClass', ma in questo caso è davvero un anti-pattern. (http://www.typescriptlang.org/Content/TypeScript%20Language%20Specification.pdf 4.13 Tipo Asserzioni) –

+0

Grazie. Quindi presumo che non sia possibile ottenere semplicemente un tipo di classe da una variabile e quindi creare una classe?instanceof richiederebbe il controllo di ogni tipo, quindi non è davvero una buona soluzione. – zeroin