给定类型“;除函数或函数“以外的任何内容;,如何检查它是否为';TypeScript中的函数是什么?

给定类型“;除函数或函数“以外的任何内容;,如何检查它是否为';TypeScript中的函数是什么?,typescript,types,conditional,Typescript,Types,Conditional,为什么值不是()=>类型的字符串在if(type of value==='function')检查之后 应进行哪些检查,以便正确推断类型(使强制转换不必要) 函数foo(值:排除|(()=>字符串)){ 让结果:字符串; 如果(值的类型==='函数'){ result=value();//错误:类型“(()=>string)|(排除和函数)”没有兼容的调用签名。 result=(value as()=>string)(;//有效,但我不喜欢它 }否则{ 结果=value.toString();

为什么
不是
()=>类型的字符串
if(type of value==='function')
检查之后

应进行哪些检查,以便正确推断类型(使强制转换不必要)

函数foo(值:排除|(()=>字符串)){
让结果:字符串;
如果(值的类型==='函数'){
result=value();//错误:类型“(()=>string)|(排除和函数)”没有兼容的调用签名。
result=(value as()=>string)(;//有效,但我不喜欢它
}否则{
结果=value.toString();
}
控制台日志(结果);
}

问题在于,当条件类型中仍有未解析的参数时(如函数内部的
t
),typescript无法对条件类型进行大量推理。因此,当遇到类型保护时,typescript只会将参数类型与
函数
相交,从而导致
(()=>string)|(Exclude&Function)
仍然无法调用

到目前为止,解决这个问题的最简单方法是使用类型断言

您也可以用不同的方式表示条件。函数必须具有
调用
方法。如果我们将
T
约束为,如果它有
call
成员,则它的类型与函数中的
call
不兼容,我们实际上将
T
排除在函数之外:

function foo<T extends number | string | boolean | null | undefined | ({ call?: undefined; [k: string]: any }) = never>(value: T | (() => string)) {
    let result: string;

    if (typeof value === 'function') {
        result = value(); // ok 
    } else {
        result = value.toString();
    }

    console.log(result);
}

foo(1)
foo({
    o: ""
})
foo(() => "");
foo(() => 1); // error
函数foo(值:T |(()=>字符串)){ 让结果:字符串; 如果(值的类型==='函数'){ 结果=值();//确定 }否则{ 结果=value.toString(); } 控制台日志(结果); } 傅(1) 福({ o:“” }) foo(()=>); foo(()=>1);//错误
也许新版本将改进typescript在涉及类型参数时的推理能力。虽然
Exclude
在过滤类型方面做得很好,但它并不能100%替代否定类型。

@Fenton这与您对类似问题的有用答案有关,所以您可能知道?谢谢!事实上,几天前有人刚刚为此创建了一个github问题:
function foo<T extends number | string | boolean | null | undefined | ({ call?: undefined; [k: string]: any }) = never>(value: T | (() => string)) {
    let result: string;

    if (typeof value === 'function') {
        result = value(); // ok 
    } else {
        result = value.toString();
    }

    console.log(result);
}

foo(1)
foo({
    o: ""
})
foo(() => "");
foo(() => 1); // error