Interfaces with string signatures do not check type

I played a bit with Type Signature Interfaces in TypeScript, and I got a little confused when the following failed to enter validation:

class Foo { constructor () { } } interface Bar { new(): Bar; } function Baz(C : Bar) { return new C() } var o = Baz(Foo); 

Type error:

The supplied parameters do not correspond to any signature of the call target: Creating signatures of types new () => Foo 'and' Bar 'are incompatible: Type' Bar 'requires a construction signature, but Type "Foo" is missing one (C: Bar) = > Bar

The constructor type is Foo - () => Foo, and that is what I thought Bar said. Did I miss something?

+9
typescript
Oct 18 '12 at 10:12
source share
4 answers

Here is an updated version of your code with subtle change.

We define the Bar interface with any functions and variables that we expect to be present.

Then we extend the Bar interface using the NewableBar interface. It just defined a constructor that returns Bar .

Since Foo implements Bar and has a constructor, and Baz requires a NewableBar , everything is checked.

This is a bit more verbose than any , but gives you the necessary verification.

 interface Bar { } interface NewableBar extends Bar { new(); } class Foo implements Bar { constructor () { } } function Baz(C : NewableBar) { return new C() } var o = Baz(Foo); 
+5
Oct 18 '12 at 11:18
source share

The problem (at least from the point of view of the TypeScript compiler) is the signature of the Bar new method. If you replace the definition of Bar with the following,

 interface Bar { new (): any; } 

it works. You can also use new (): Foo , just Bar , since the return value does not work.

+1
Oct 18 '12 at 10:26
source share

I think I know where you are doing this, and I think you need a subtle approach.

This example says the following:

  • Baz must pass on an item that is new.
  • Baz will return a string
  • Not all bars should be new, only those that are transferred to Baz

Here is an example:

 interface Bar { sayHello(name: string): void; } interface Newable { new(); } class Foo implements Bar { constructor () { } sayHello(name: string) { window.alert('Hello ' + name); } } function Baz(C : Newable) { return <Bar> new C() } var o = Baz(Foo); o.sayHello('Bob'); 

The only danger with this approach is that you can convey something new that was not a bar for the Baz function. Since you are using a dynamic function to create an object from an argument, this is pretty much inevitable if you did not want to pass a pre-initialized object, in which case Baz would happily agree with the bar and not with the new one.

+1
Oct 18
source share

I know this is an old question, but I needed something similar today and came across a message. After some trial and error, I came up with the following solution:

 interface Bar { sayHello(name: string); } class Foo implements Bar { sayHello(name: string) { window.alert("Hello " + name); } } function Baz(c: new() => Bar) { return new C(); } var o = Baz(Foo); o.sayHello("Bob"); 

Basically, interfaces can define a contract only for an instance of an object, so the requirement for the existence of a particular constructor must be satisfied in the function that the constructor will call. This method goes well with generics:

 function Baz<T extends Bar>(c: new() => T) { return new c(); } var o = Baz(Foo); 

In the above example, the variable "o" will be output as type Foo.

+1
Aug 14 '14 at 4:26
source share



All Articles