问题是这两个函数有不同的签名,因此索引操作的结果将是两个签名的联合,根据定义,这两个签名是不可调用的。
Function
方法
call
或
apply
可访问(因为它们对联合体中的两个签名都是通用的)来调用函数,但缺点是会丢失所有类型安全性:
if (typeof firstDeferedCmd == "object" && ( firstDeferedCmd.type === "execute" || firstDeferedCmd.type === "execSpawn" )) {
ProcessPoolExecutor[firstDeferedCmd.type].call(ProcessPoolExecutor, firstDeferedCmd);
}
您可以始终使用断言使联合可调用,但这样做并不安全
:
if (typeof firstDeferedCmd == "object" && ( firstDeferedCmd.type === "execute" || firstDeferedCmd.type === "execSpawn" )) {
(ProcessPoolExecutor[firstDeferedCmd.type] as (cmd: IDeferedCmd) => Promise<{stdout: string;stderr: string;}> | Promise<NodeJS.ReadableStream>)(firstDeferedCmd);
}
您还可以使用两个检查来指定两个不同的签名,这实际上暴露了当前设计的一个问题:
function fn(firstDeferedCmd : IDeferedCmd){
if (typeof firstDeferedCmd == "object") {
if(firstDeferedCmd.type === "execute") {
return ProcessPoolExecutor[firstDeferedCmd.type](firstDeferedCmd);
}
if(firstDeferedCmd.type === "execSpawn") {
if(firstDeferedCmd.args){
return ProcessPoolExecutor[firstDeferedCmd.type](firstDeferedCmd); // error since there is no requirement if execSpawn is specified to also specify args
}
}
}
}
我们可以通过改变
IDeferedCmd
type IDeferedCmd = {
type: "execute",
cmd: string,
name: string,
} | {
type: "execSpawn",
cmd: string,
name: string,
resolve: IResolveFn,
reject: IRejectFn,
args: Array<string>,
options: object
}
function fn(firstDeferedCmd : IDeferedCmd){
if (typeof firstDeferedCmd == "object") {
if(firstDeferedCmd.type === "execute") {
return ProcessPoolExecutor[firstDeferedCmd.type](firstDeferedCmd);
}
if(firstDeferedCmd.type === "execSpawn") {
if(firstDeferedCmd.args){
return ProcessPoolExecutor[firstDeferedCmd.type](firstDeferedCmd); // ok now
}
}
}
}