打字签名与结构签名是如何工作的?

我遇到了一些麻烦,如何在接口中定义构造函数。 我可能完全误解了一些东西。 但是我已经search了很长一段时间的答案,我找不到与此相关的任何内容。

如何在TypeScript类中实现以下接口:

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

Anders Hejlsberg在本video中创build了一个包含类似内容的界面(大约14分钟)。 但是对于我来说,我不能在课堂上实现这一点。

我可能误解了一些东西,我没有得到什么?

编辑:

澄清。 与“新(…)”我的意思是“任何事情”。 我的问题是,我无法得到这个工作的最基本的版本:

 interface MyInterface { new () : MyInterface; } class test implements MyInterface { constructor () { } } 

这不是我编译我得到“类'testing'声明接口'MyInterface',但没有实现它:types'MyInterface'需要一个构造签名,但types'testing'缺乏一个”试图编译它。

编辑:

所以在研究了这一点之后再给予反馈。

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

是无效的TypeScript,这并不能解决问题。 您不能定义构造函数的返回types。 它会返回“testing”。 下面的签名:class test {constructor(){}}看起来是“new()=> test”(通过粘贴在代码上的鼠标hover在在线编辑器中的“class”获得)。 这就是我们想要的和我认为会是的。

任何人都可以提供这样的例子或类似的地方,它实际上是编译?

编辑(再次…):

所以我可能想出了一个想法,为什么可以在一个接口中定义这个,但不能在TypeScript类中实现。下面的工作:

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

那么这只是TypeScript的一个function,可以让你界面的JavaScript? 或者有可能在TypeScript中实现它,而不必使用JavaScript实现类?

在接口中构造签名不能在类中实现; 他们只是为了定义现有的JS API来定义一个“新”function。 下面是一个涉及接口的new签名的例子:

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

这为您可以调用makeObj创build一个实际约束:

 class Other implements ComesFromString { constructor (public name: string, count: number) { } } makeObj(Other); // Error! Other's constructor doesn't match StringConstructable 

在我的search完全相同的问题,我去看TypeScript-Team如何做…

他们正在声明一个接口,然后声明一个名称完全匹配接口名称的variables。 这也是键入静态函数的方法。

来自lib.d.ts示例:

 interface Object { toString(): string; toLocaleString(): string; // ... rest ... } declare var Object: { new (value?: any): Object; (): any; (value: any): any; // ... rest ... } 

我试过了,它的作用像魅力。

从devise的angular度来看,通常不需要在接口中指定构造函数的需求。 界面应该描述你可以在一个对象上执行的操作。 实现接口的不同类应该被允许在需要的时候需要不同的构造器参数。

例如,如果我有一个接口:

 interface ISimplePersistence { load(id: number) : string; save(id: number, data: string): void; } 

我可能有实现将数据存储为一个不需要构造函数参数的cookie,以及将数据存储在数据库中的版本,该数据库需要连接string作为构造函数参数。

如果你仍然想要在界面中定义构造函数,有一个肮脏的方法来做到这一点,我曾经回答这个问题:

与构造签名的接口不进行types检查

为了实现预期的行为,你可以使用装饰器 ,即使这可能不是他们应该使用的。

这个

 interface MyInterface { new (); } function MyInterfaceDecorator(constructor: MyInterface) { } @MyInterfaceDecorator class TestClass { constructor () { } } 

编译没有问题。 相比之下,TestClass的定义如下

 // error TS2345: Argument of type 'typeof TestClass' is not assignable to parameter of type 'MyInterface'. @MyInterfaceDecorator class TestClass { constructor (arg: string) { } } 

不会编译。