为了减少对老化的灰质的认知负担,我为事件发射器中的特定事件提供自定义重载。
// 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"
)分隔却可以正常工作?
答案 0 :(得分:1)
为了使编译器能够选择正确的类型检查,它遵循与基础JavaScript相似的过程。它查看重载列表,并进行第一个重载尝试以提供的参数调用该函数。如果找到匹配项,它将选择此重载作为正确的重载。 因此,习惯上将重载从最具体到最不具体排序。
我确实看到,有时编译器的确会通过查找更具体的签名来“无序地”选择重载,即使它们不是列表中的第一个匹配签名(例如,参见GitHub issue 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) {
// ...
}
这应该可以按照您想要的方式工作。希望能有所帮助。祝你好运!