Nypan Nypan - 3 months ago 15
TypeScript Question

How does typescript interfaces with construct signatures work?

I am having some trouble working out how defining constructors in interfaces work. I might be totally misunderstanding something. But I have searched for answers for a good while and I can not find anything related to this.

How do I implement the following interface in a TypeScript class:

interface MyInterface {
new ( ... ) : MyInterface;
}


Anders Hejlsberg creates an interface containing something similar to this in this video (at around 14 minutes). But for the life of me I can not implement this in a class.

I am probably misunderstanding something, what am I not getting?

EDIT:

To clarify. With "new ( ... )" I meant "anything". My problem is that I can not get even the most basic version of this working:

interface MyInterface {
new () : MyInterface;
}

class test implements MyInterface {
constructor () { }
}


This is not compiling for me I get "Class 'test' declares interface 'MyInterface' but does not implement it: Type 'MyInterface' requires a construct signature, but Type 'test' lacks one" when trying to compile it.

EDIT:

So after researching this a bit more given the feedback.

interface MyInterface {
new () : MyInterface;
}

class test implements MyInterface {
constructor () => test { return this; }
}


Is not valid TypeScript and this does not solve the problem. You can not define the return type of the constructor. It will return "test". The signature of the following:
class test {
constructor () { }
}
Seems to be "new () => test" (obtained by hovering over "class" in the online editor with just that code pasted in). And this is what we would want and what i thought it would be.

Can anyone provide an example of this or something similar where it is actually compiling?

EDIT (again...):

So I might have come up with an idea as to why it is possible to define this in an interface but not possible to implement in a TypeScript class.The following works:

var MyClass = (function () {
function MyClass() { }
return MyClass;
})();

interface MyInterface {
new () : MyInterface;
}

var testFunction = (foo: MyInterface) : void => { }
var bar = new MyClass();
testFunction(bar);


So is this only a feature of TypeScript that lets you interface javascript? Or is it possible to implement it in TypeScript without having to implement the class using javascript?

Answer

Construct signatures in interfaces are not implementable in classes; they're only for defining existing JS APIs that define a 'new'-able function. Here's an example involving interfaces new signatures that does work:

interface ComesFromString {
    name: string;
}

interface StringConstructable {
    new(n: string): ComesFromString;
}

class MadeFromString implements ComesFromString {
    constructor (public name: string) {
        console.log('ctor invoked');
    }
}

function makeObj(n: StringConstructable) {
    return new n('hello!');
}

console.log(makeObj(MadeFromString).name);

This creates an actual constraint for what you can invoke makeObj with:

class Other implements ComesFromString {
    constructor (public name: string, count: number) {
    }
}

makeObj(Other); // Error! Other's constructor doesn't match StringConstructable
Comments