2012-10-08 21 views
14

Me pregunto cómo puedo obtener una referencia a un constructor de tipos para pasar la función como un valor. Básicamente, me gustaría tener un registro de tipo genérico que permita crear instancias llamando a una función miembro de una instancia de registro de tipo genérico.Hace referencia a la función de constructor

Por ejemplo:

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

después:

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

Alguien sabe si es posible hacer referencia a una función de constructor de clases?

Respuesta

18

Puede usar el tipo de constructor literal o un tipo de objeto literal con una firma de construcción para describir el tipo de un constructor (consulte, en general, la sección 3.5 de la especificación de idioma). Para utilizar el ejemplo, lo siguiente debería funcionar:

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

Aviso el constructor de tipo literal en la lista de parámetros del constructor GenometryTypeInfo, y la nueva llamada en la implementación de createInstance.

+0

Gracias, me perdí el 'nuevo' literal en la especificación. –

+1

en '// <- falla' Supongo que como es la solución, ya no falla, si es correcto, ¿puede editarla a' // <- no falla más' o algo similar? De lo contrario, es un poco engañoso, thx – peter

6

typeof YourClass le ofrece el constructor tipo que se puede utilizar en el tipo de anotaciones.

YourClass y this.constructor es el propio constructor. Por lo tanto, este código se compila:

class A {} 

const B : typeof A = A; 

this.constructor no se reconoce como valor de tipo constructor por mecanografiado (que es divertido), por lo que en situaciones como la que tiene que utilizar un poco de engaño lanzarlo sin any

new (<any> this.constructor)()

Eso es todo.

+0

El problema con esta solución es OP quiere hacer referencia al tipo "constructor de un tipo que implementa una interfaz", y creo que no se puede decir 'typeof IGeometry' cuando' IGeometry' es una interfaz . En el caso donde el param pasado es un constructor para una clase o super clase dada, este es un gran método. – jkjustjoshing

+1

'interfaz MyCtor {new(): MyInterface}' debería hacer el trabajo entonces. – gaperton

+2

Pero prefiero 'typeof Class' siempre que sea posible. Es más específico y maneja la cadena de herencia correctamente. – gaperton

Cuestiones relacionadas