1

为了减少对老化灰质的认知负担,我正在为事件发射器中的特定事件提供自定义重载。

// default signature
function on(event: string | symbol, listener: (...args: any[]) => void): void;
// custom signatures
function on(event: "error", listener: (error: string, code: number) => void): void;
function on(event: "data", listener: (text: string) => void): void;
function on(event: "chunk", listener: (text: string) => void): void;
function on(event: "complete" | "done", listener: (id: number) => void): void;
// most general signature
function on(event: any, listener: (...args: any[]) => void) {
  // ...
}

// correctly resolve data as 'string'
on("data", (data) => {});
on("chunk", (data) => {});
// incorrectly resolves id as any from default signature
on("complete", (id)  => {});

根据 TypeScript 文档,我在特定重载之后订购了一般重载。

我的问题是;为什么联合类型 ( "complete" | "done") 不能按预期工作,但将它们 ( "data" and "chunk") 分开?

4

1 回答 1

1

有关重载的文档中

为了让编译器选择正确的类型检查,它遵循与底层 JavaScript 类似的过程。它查看重载列表,并继续第一次重载尝试使用提供的参数调用函数。如果找到匹配项,它将选择此重载作为正确的重载。出于这个原因,习惯上按照从最具体到最不具体的顺序对重载进行排序。

我确实看到有时编译器确实会通过查找更具体的签名来“乱序”选择重载,即使它们不是列表中的第一个匹配签名(例如,请参阅GitHub 问题 Microsoft/TypeScript#9443)......但是当毫无疑问,如果您将重载从最具体到最一般列出,您将获得最佳行为。例如:

// custom signatures
function on(event: "error", listener: (error: string, code: number) => void): void;
function on(event: "data", listener: (text: string) => void): void;
function on(event: "chunk", listener: (text: string) => void): void;
function on(event: "complete" | "done", listener: (id: number) => void): void;
// default signature
function on(event: string | symbol, listener: (...args: any[]) => void): void;
// implementation signature
function on(event: any, listener: (...args: any[]) => void) {
  // ...
}

这应该按您的意愿工作。希望有帮助。祝你好运!

于 2019-03-04T20:16:37.710 回答