我遇到错误
Cannot invoke an expression whose type lacks a call signature ... has no compatible call signatures.
关于我的一种方法,我不知道如何解决它。 我已经看到了此链接cannot-invoke-an-expression-whose-type-lacks-a-call-signature
还有2个,但仍然没有设法解决
类型声明:
type ProcessMethods = "execute" | "execSpawn"
interface IDeferedCmd {
type: ProcessMethods,
cmd: string,
name: string,
resolve: IResolveFn,
reject: IRejectFn,
args?: Array<string>,
options?: object
}
在我的课堂上,我有2个看起来像这样的静态方法
static execute({cmd, name}: { cmd: string, name: string }): Promise<{
stdout: string;
stderr: string;
}>
static execSpawn({cmd, name, args , options }: { cmd: string, name: string, args: Array<string>, options: object }): Promise<NodeJS.ReadableStream>
和女巫中的第三个方法尝试动态调用它们会引发错误
if (typeof firstDeferedCmd == "object" && ( firstDeferedCmd.type === "execute" || firstDeferedCmd.type === "execSpawn" )) {
ProcessPoolExecutor[firstDeferedCmd.type](firstDeferedCmd); // this line throw the error
}
错误及其自身
无法调用类型缺少调用签名的表达式。键入'(({{cmd,name}:{cmd:string; name:string;})=> Promise <{}>)| (({{cmd,name,args,options} ...'没有兼容的呼叫签名。 ProcessPoolExecutorfirstDeferedCmd.type; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~
答案 0 :(得分:1)
问题在于这两个函数具有不同的签名,因此索引操作的结果将是两个签名的并集,根据定义,它们是不可调用的。
您可以使用Function
方法call
或apply
来访问函数(因为它们对于联合中的两个签名都是通用的),因此会丢失所有的缺点类型安全性:
if (typeof firstDeferedCmd == "object" && ( firstDeferedCmd.type === "execute" || firstDeferedCmd.type === "execSpawn" )) {
ProcessPoolExecutor[firstDeferedCmd.type].call(ProcessPoolExecutor, firstDeferedCmd);
}
您总是可以使用断言来使联合可调用,但这比call
更加安全:
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
}
}
}
}