1

Closed

Implement a newable interface

description

The following gives an error :
interface Foo{
    new (x:number)
}

class Bar implements Foo{
    constructor(x:number){}
}
The error reads:
'Foo' requires a construct signature but 'Bar' lacks one.
However they are inter-assignable i.e. the types match:
interface Foo{
    new (x:number)
}

class Bar{
    constructor(x:number){}
}

var foo:Foo; 
var bar:Bar;
foo=bar=foo; // They are inter assignable 
Is the inability to implement such an interface by design? If so the error statement could use a rewording e.g. cannot implement a newable interface since the types are actually compatible.
Closed Oct 7, 2013 at 4:22 PM by RyanCavanaugh
Classes cannot implement construct signatures for the same reason they cannot implement call signatures. See http://stackoverflow.com/a/13408029/1704166 for some details there.

In your second code snippet, note that foo = bar = foo is not a way to check for interassignability of two expressions. Because the type of an assignment expression is the type of the right operand, that statement only checks that foo is assignable to bar. Foo is assignable to an instance of Bar because Foo has all of the members of an instance of Bar (all zero of them). An instance of Bar is not assignable to Foo because it lacks a construct signature (foo = bar correctly produces an error).

comments

mindplay wrote Oct 6, 2013 at 4:13 PM

The manual does not mention this feature, so I think this may be missing by design.

As far as the syntax, my guess would have been:
interface Foo {
    constructor(x: number);
}
Interestingly, this is valid syntax - however, attempting to implement this interface, you will get an error-message about a missing property named "constructor", so no dice.

I also attempted declaring a static method create as part of the interface, thinking you could accomplish the same thing by enforcing the presence of a static factory-method (rather than a specific constructor) on every class; unfortunately, static declarations are not allowed in interface declarations either.

I remember running into the same thing with C# in the past, and I'm afraid you're going to find the answer is always in the negative. The typical explanation is something along the lines of this: you're trying to use interfaces to specify a "contract" to which your types need to conform - but that's not what interfaces do, they specify how the objects need to conform.

Whether you agree with that or not (and I don't) that is most likely the answer you're going to get.

There is a work-around, however - it's a little more complicated, and involves introducing an object that represents each type. In the long run, this may turn out to be an advantage - if you'd like, you can read my very long explanation on StackOverflow.