打字签名与结构签名是如何工作的?
我遇到了一些麻烦,如何在接口中定义构造函数。 我可能完全误解了一些东西。 但是我已经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) { } }
不会编译。