Typescript 类型脚本类型T或函数()=>;T用法

Typescript 类型脚本类型T或函数()=>;T用法,typescript,Typescript,您可以在中看到演示 我创建了一个简单的泛型类型,它可以表示变量或返回变量的函数。但是,不幸的是,它不适用于典型的typeof arg==“function”检查。它会产生以下错误: 此表达式不可调用。 不是所有类型为“(()=>T)|(T&Function)”的组件都可以调用。 类型“T&Function”没有调用签名。 有没有一种方法可以使它不使用类型保护功能而工作 类型初始值设定项=T |(()=>T) 函数正确(参数:初始值设定项){ 返回类型arg===“函数”?arg():arg }

您可以在中看到演示

我创建了一个简单的泛型类型,它可以表示变量或返回变量的函数。但是,不幸的是,它不适用于典型的
typeof arg==“function”
检查。它会产生以下错误:

此表达式不可调用。
不是所有类型为“(()=>T)|(T&Function)”的组件都可以调用。
类型“T&Function”没有调用签名。

有没有一种方法可以使它不使用类型保护功能而工作

类型初始值设定项=T |(()=>T)
函数正确(参数:初始值设定项){
返回类型arg===“函数”?arg():arg
}
函数错误(参数:初始值设定项){
返回类型arg===“函数”?arg():arg//此处出错
}
常量isFunction=(arg:any):arg是Function=>typeof arg==='Function'
函数正确_2(参数:初始值设定项){
返回isFunction(arg)?arg():arg
}
您可以编写:

type Initializer<T> = T extends any ? (T | (() => T)) : never

function correct<T>(arg: Initializer<T>): T {
    return typeof arg === 'function' ? arg() : arg // works
    // arg is Initializer<T> & Function in the true branch
}

const r1 = correct(2) // const r1: 2
const r2 = correct(() => 2) // const r2: number
type Initializer=T扩展了什么?(T |(()=>T)):从不
函数正确(参数:初始值设定项):T{
返回类型arg==“函数”?arg():arg//works
//arg是true分支中的初始值设定项和函数
}
常数r1=正确(2)//常数r1:2
常数r2=正确(()=>2)//常数r2:编号
在原始版本中,
arg
在真分支中解析为
(()=>T)|(T&Function)
。TS显然无法识别这种联合函数类型的两个成分都是可调用的。至少在上面的版本中,编译器很清楚,在函数检查之后可以调用
arg


对于TypeScript存储库中的这种情况,可能也值得一提-在我看来,
T&Function
应该代表某种(广泛的)函数类型。

我尝试了一种不同于公认答案的方法,禁止T(预期解析值)为函数。它似乎适用于大多数用例,除非您试图从初始值设定项生成函数

type Initializer<T> = T extends Function ? never : T | (() => T);

function foo<T>(r: Initializer<T>): T {
  return typeof r === 'function' ? r() : r;
}


const valOK = foo('2');
const funOK = foo(() => 4);

const funError = foo((a: number, b: number) => a + b);  // Expected error
type Initializer=T扩展函数?从不:T |(()=>T);
函数foo(r:初始值设定项):T{
返回类型r=='函数'?r():r;
}
const valOK=foo('2');
常数funOK=foo(()=>4);
const funError=foo((a:number,b:number)=>a+b);//预期误差

使用
instanceof Function
检查
arg
是否可调用,效果良好:

类型初始值设定项=T |(()=>T)
函数已修复(参数:初始值设定项){
//而不是使用“typeof”:
//返回类型arg===“函数”?arg():arg//此处出错
//使用`instanceof`
返回函数的arg实例?arg():arg
}

这最初是由描述的。

这是一个聪明的把戏,谢谢。我已经创建了一个问题。嘿,GitHub的问题说这个技巧就是bug,并且原始行为是正确的(这一部分是有意义的,因为如果
T
本身是一个类似
(x:string)=>number
,那么调用
arg()是不安全的
。使用函数的
实例也是一个很好的解决方法