19

Im wondering how I can get a reference to a types constructor to pass the function as a value. Basically, I would like to have a generic type registry that would allow instances to be created by calling a member function of a generic type registry instance.

For example:

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

Later:

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

Anyone know if it is possible to reference a classes constructor function?

2 Answers 2

22

You can use the constructor type literal or an object type literal with a construct signature to describe the type of a constructor (see, generally, section 3.5 of the language spec). To use your example, the following should work:

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

Notice the constructor type literal in GeometryTypeInfo's constructor parameter list, and the new call in the implementation of createInstance.

Sign up to request clarification or add additional context in comments.

1 Comment

in // <- fails I suppose as it's the solution, it doesn't fail anymore, if that's correct maybe you can edit it to // <- doesn't fail anymore or something similar? Otherwise it's a bit misleading, thx
10

typeof YourClass gives you constructor type which can be used in type annotations.

YourClass and this.constructor is constructor itself. So, this code compiles:

class A {}

const B : typeof A = A;

this.constructor is not recognized as value of constructor type by TypeScript (which is funny), so in situations like that you need to use some cheating casting it no any

new (<any> this.constructor)()

That's it.

6 Comments

The issue with this solution is OP wants to reference the type "constructor of a type that implements an interface", and I believe you can't say typeof IGeometry when IGeometry is an interface. In the case where the passed param is a constructor for a given class or super class this is a great method.
interface MyCtor { new () : MyInterface } should do the job then.
But I prefer typeof Class whenever possible. It's more specific and handles inheritance chain properly.
That wouldn't work in this case, since the constructor's signature is new (x: number, y: number): Point. And what happens when each class that implements it has a different constructor signature?
Cause, polymorphic code you would probably write (class factory, as I understand from the context) would expect the same signature from all the subclasses' constructors.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.