带有构造签名的接口如何工作?

新手上路,请多包涵

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

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

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

Anders Hejlsberg 在此 视频 中创建了一个包含类似内容的界面(大约 14 分钟)。但是对于我的一生,我无法在课堂上实现这一点。

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

编辑:

澄清。对于“新(…)”,我的意思是“任何东西”。我的问题是我什至无法获得这个工作的最基本版本:

 interface MyInterface {
    new () : MyInterface;
}

class test implements MyInterface {
    constructor () { }
}

这不是为我编译我在尝试编译时得到“类’test’声明接口’MyInterface’但没有实现它:类型’MyInterface’需要构造签名,但类型’test’缺少一个”。

编辑:

因此,在给出反馈后,对此进行了更多研究。

 interface MyInterface {
    new () : MyInterface;
}

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

不是有效的 TypeScript,这并不能解决问题。你不能定义构造函数的返回类型。它将返回“测试”。以下内容的签名: class test { constructor () { } } 似乎是“new () => test”(通过在在线编辑器中将鼠标悬停在“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 的一个功能,可以让您与 javascript 交互吗?或者是否可以在 TypeScript 中实现它而无需使用 javascript 实现类?

原文由 Nypan 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 894
2 个回答

接口中的构造签名不能在类中实现;它们仅用于定义定义“新”功能的现有 JS API。这是一个涉及接口 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

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

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

原文由 Ryan Cavanaugh 发布,翻译遵循 CC BY-SA 3.0 许可协议

来自官方 文档

这是因为当一个类实现一个接口时,只检查类的实例端。由于构造函数位于静态端,因此它不包含在此检查中。

相反,您需要直接使用类的静态部分。在本例中,我们定义了两个接口,ClockConstructor 用于构造函数,ClockInterface 用于实例方法。然后,为方便起见,我们定义了一个构造函数 createClock 来创建传递给它的类型的实例:

 interface ClockConstructor {
  new (hour: number, minute: number): ClockInterface;
}

interface ClockInterface {
  tick(): void;
}

function createClock(
  ctor: ClockConstructor,
  hour: number,
  minute: number
): ClockInterface {
  return new ctor(hour, minute);
}

class DigitalClock implements ClockInterface {
  constructor(h: number, m: number) {}
  tick() {
    console.log("beep beep");
  }
}

class AnalogClock implements ClockInterface {
  constructor(h: number, m: number) {}
  tick() {
    console.log("tick tock");
  }
}

let digital = createClock(DigitalClock, 12, 17);
let analog = createClock(AnalogClock, 7, 32);

原文由 Azat 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进