Typescript 如何断言类型脚本泛型类型

Typescript 如何断言类型脚本泛型类型,typescript,generics,typescript-generics,Typescript,Generics,Typescript Generics,我试图用映射类型和泛型综合这些重载 function x(_: BooleanConstructor): boolean function x(_: StringConstructor): string function x(_: NumberConstructor): number function x<T>(_: Constructor<T>): T 函数x(quo:BooleanConstructor):boolean 函数x(ux0:StringConstruc

我试图用映射类型和泛型综合这些重载

function x(_: BooleanConstructor): boolean
function x(_: StringConstructor): string
function x(_: NumberConstructor): number
function x<T>(_: Constructor<T>): T
函数x(quo:BooleanConstructor):boolean
函数x(ux0:StringConstructor):字符串
函数x(uu:NumberConstructor):数字
函数x(构造函数):T
但是我有很多困难,尤其是这个

我想知道为什么下面的代码不起作用

export type Constructor<T> = new (...args: any[]) => T
export type MappedResult<T> =
    T extends Boolean ? boolean :
    T extends Number ? number :
    T extends String ? string :
    T

function make<T, Ctor = Constructor<T>, Result = MappedResult<T>>(ctor: Ctor): Result {
    if (ctor === String) { return '' } // would produce error
    throw new Error()
}

const str = make<String, StringConstructor, string>(String) // string!
const wrongInferenceStr = make(String) // would be {}
导出类型构造函数=new(…args:any[])=>T 导出类型MappedResult= T扩展布尔?布尔值: T扩展数字?编号: T扩展字符串?字符串: T 函数生成(ctor:ctor):结果{ 如果(ctor==String){return'}//将产生错误 抛出新错误() } const str=make(String)//String! const errore推论str=make(String)//将是{} 我的理解是,在TypeScript 3.0中,
T
更像是新的
unknown
类型,因此我必须声明它的标识,有什么办法吗

更新 使用jcalz的答案,我尝试使用,但没有运气


简而言之,我认为编译器有缺陷

要在调用
make
时获得正确的推理,其签名最好需要尽可能简单的推理。这意味着:为编译器提供最少的决策空间,并尽可能直接地做出决策。例如,只有一个类型参数与
ctor
参数的类型完全对应,然后使用条件类型计算输出的相关类型。像这样:

declare function make<C extends Constructor<any>>(ctor: C): 
  MappedResult<C extends Constructor<infer T> ? T : never>;

至于
make
实现中的错误,编译器通常不够聪明,不喜欢
C
StringConstructor
,并且会抱怨。处理这一问题的最简单方法通常是对调用方签名使用单个签名,并使实现签名具有更大的权限(但类型安全性较低)。例如:

function make<C extends Constructor<any>>(ctor: C): MappedResult<C extends Constructor<infer T> ? T : never>;
function make(ctor: Constructor<any>): any {
    if (ctor === String) { return '' } // no error now
    throw new Error()
}
函数make(ctor:C):MappedResult;
函数生成(ctor:构造函数):任意{
if(ctor==String){return'}//现在没有错误
抛出新错误()
}
这是可行的,但是您必须小心实现,因为返回类型是
any
。这类似于断言。不确定这里是否有一个聪明的方法来保证类型安全。。。但你可能不需要它



希望有帮助。祝你好运

按照您的建议,我遇到了另一个问题,
tsc
现在抱怨相同的导出类型是同名的不同类型。请参阅更新。是的,这是一个不同的问题,我同意这似乎是一个编译器错误。构造函数是什么时候从TS中消失的?据我所知,TS中从来没有一个名为
Constructor
的实用程序类型。如果您想要这样一个类型,您必须声明它,如上面的问题代码所示。
function make<C extends Constructor<any>>(ctor: C): MappedResult<C extends Constructor<infer T> ? T : never>;
function make(ctor: Constructor<any>): any {
    if (ctor === String) { return '' } // no error now
    throw new Error()
}