如何在 TypeScript 中正确使用 Function 的构造签名

Onl*_*ick 2 typescript

我正在阅读 TS 文档,当我阅读More on Functions 时,我不明白下面的代码,如何在实际开发中使用它。有没有例子?

interface CallOrConstruct {
  new (s: string): Date;
  (n?: number): number;
}
Run Code Online (Sandbox Code Playgroud)

Jef*_*ica 5

您在此处看到的是一个具有不同行为的对象,具体取决于您是否使用new. 这是 Javascript 能够做的事情,但会导致代码混乱;您可能很少会看到这种签名,或者在为 Typescript 使用改编非常旧或灵活的 Javascript 库时。

(从技术上讲,行为不必有所不同:无论是否new具有相同的整体行为,敏感对象都可以调用,并且需要调用构造签名。但是,这种故意的灵活性仍然不寻常。谢谢@kaya3 !)


您的代码段出现在更多关于函数的文本下方:

一些对象,如 JavaScript 的Date对象,可以使用或不使用new. 您可以任意组合相同类型的调用和构造签名:

这是对内置 Date 对象的引用,该对象在 MDN 上以下文本

Date()

当作为函数调用时,返回当前日期和时间的字符串表示形式,完全一样new Date().toString()

new Date()

当作为构造函数调用时,返回一个新Date对象。

console.log(typeof Date())      // string
console.log(typeof new Date())  // object
Run Code Online (Sandbox Code Playgroud)

如上所述,单个 Function 对象同时服务于两个目的是非常罕见的:您通常会看到一个函数/类被故意调用为一个或另一个,但不会两者兼而有之。但是,因为可以在 Javascript 中完成(甚至可以在内置对象中完成),所以 TypeScript 能够表示在两种调用样式中都可以工作的对象非常重要。

interface CallOrConstruct {
  new (s: string): Date;      // construct
  (n?: number): number;       // call
}

// construct
let object: Date = new CallOrConstruct("optional string s");

// call
let myNumber: number = CallOrConstruct(/* n= */ 42);
Run Code Online (Sandbox Code Playgroud)

您可能永远不需要输入这样的接口,特别是如果您为类和(或其他普通函数声明)使用classand为您的函数。如果您尝试声明 TypeScript 不理解的类型(如在外部 Javascript 库TypeScript 声明文件中),或者如果您尝试编写一个聪明且容易混淆的 TypeScript 对象,您只需这样做两种方式使用。就我自己而言,我没有理由像这样写我自己的声明,尽管我在图书馆和他们的类型中读过一些。 constructor function.d.ts