2012-10-08 24 views
14

Mi chiedo come ottenere un riferimento a un costruttore di tipi per passare la funzione come valore. Fondamentalmente, vorrei avere un registro di tipo generico che consenta di creare istanze chiamando una funzione membro di un'istanza di registro di tipo generico.Riferimento alla funzione costruttore

Ad esempio:

class GeometryTypeInfo 
{   
    constructor (public typeId: number, public typeName: string, public fnCtor: (...args: any[]) => IGeometry) { 
    } 
    createInstance(...args: any[]) : IGeometry { return this.fnCtor(args); } 
    } 
} 

tardi:

class Point implements IGeometry { 
    constructor(public x: number, public y: number) { } 

    public static type_info = new GeometryTypeInfo(1, 'POINT', Point); // <- fails 
    // also fails: 
    // new GeometryTypeInfo(1, 'POINT', new Point); 
    // new GeometryTypeInfo(1, 'POINT', Point.prototype); 
    // new GeometryTypeInfo(1, 'POINT', Point.bind(this)); 
} 

Qualcuno sa se è possibile fare riferimento a una funzione di classi di costruzione?

risposta

18

È possibile utilizzare il letterale di tipo costruttore o un letterale di tipo oggetto con una firma di costrutto per descrivere il tipo di un costruttore (vedere, in generale, la sezione 3.5 delle specifiche del linguaggio). Per utilizzare il vostro esempio, il seguente dovrebbe funzionare:

interface IGeometry { 
    x: number; 
    y: number; 
} 

class GeometryTypeInfo 
{   
    constructor (public typeId: number, public typeName: string, public fnCtor: new (...args: any[]) => IGeometry) { 
    } 
    createInstance(...args: any[]) : IGeometry { return new this.fnCtor(args); } 
} 

class Point implements IGeometry { 
    constructor(public x: number, public y: number) { } 

    public static type_info = new GeometryTypeInfo(1, 'POINT', Point); 
} 

Avviso tipo costruttore letterale nella lista parametro del costruttore di GenometryTypeInfo, e la nuova chiamata nella realizzazione di createInstance.

+0

Grazie, ho perso il "nuovo" letterale nelle specifiche. –

+1

in '// <- fail' Suppongo che siccome è la soluzione, non fallisce più, se è corretto forse puoi modificarlo in' // <- non fallire più' o qualcosa di simile? Altrimenti è un po 'fuorviante, grazie – peter

6

typeof YourClass fornisce al costruttore il tipo che può essere utilizzato nelle annotazioni di tipo.

YourClass e this.constructor è il costruttore stesso. Quindi, questo codice viene compilato:

class A {} 

const B : typeof A = A; 

this.constructor non è riconosciuto come valore di tipo costruttore dal dattiloscritto (che è divertente), quindi in situazioni del genere è necessario utilizzare un po 'di barare il cast non any

new (<any> this.constructor)()

Questo è tutto.

+0

Il problema con questa soluzione è OP che fa riferimento al tipo "costruttore di un tipo che implementa un'interfaccia", e credo che non si possa dire "tipo di IGeometry" quando "IGeometry" è un'interfaccia . Nel caso in cui il parametro passato sia un costruttore per una determinata classe o super classe, questo è un ottimo metodo. – jkjustjoshing

+1

'interfaccia MyCtor {new(): MyInterface}' dovrebbe fare il lavoro allora. – gaperton

+2

Ma preferisco 'typeof Class' quando possibile. È più specifico e gestisce correttamente la catena di ereditarietà. – gaperton

Problemi correlati