为什么TypeScript中Parameters可推断泛型参数但infer不行?
问题根因
你遇到的差异本质是TypeScript对逆变位点的infer推断规则与元组类型推断规则的不同:
- 你定义的
Filter<T>接口中,泛型参数T处于函数参数位置,属于逆变位点。在TS 4.7之前,逆变位点的无修饰infer T会默认返回该位点的上界(无显式约束时上界为unknown),无法正确推导实际的参数类型;而TS 4.7之后默认对infer使用协变推断规则,逆变位点不加修饰符也会返回不符合预期的unknown。 - 内置工具类型
Parameters的实现是直接推断函数的剩余参数元组infer P,元组类型的推断不受单类型逆变/协变规则影响,因此可以正确拿到实际参数类型。
解决方案
方案1:使用infer逆变修饰符(TS 4.7+ 推荐)
TS 4.7引入了infer的方差修饰符,在逆变位点做推断时加上in关键字即可正确推导参数类型,完全满足你希望用infer做自定义类型提取的需求,修改后代码如下:
// 给逆变位置的infer加上in修饰符 type InpInfer<F extends Filter<never>> = F extends Filter<infer in T> ? T : never;
修改后wrapInfer函数会正常编译,不会报类型不兼容错误,且推导出来的T类型为实际入参类型,无特殊指定时默认为unknown,符合你做类型交叉的要求。
方案2:自定义参数提取工具类型(兼容低版本TS)
如果需要兼容TS 4.7以下版本,可以自己实现和Parameters行为一致的提取类型,直接对函数调用签名做参数推断,避开逆变位点的单独infer:
type ExtractFilterParam<F extends Filter<never>> = F extends (inp: infer T) => boolean ? T : never;
该方案同样可以正确提取参数类型,推导结果和Parameters完全一致。
类型范围问题修复
你观察到的Parameters返回undefined属于未指定泛型具体类型时的默认推断行为,只要给泛型添加默认约束即可解决:
// 给F添加默认类型,未指定时参数类型为unknown function wrapInfer<F extends Filter<never> = Filter<unknown>>(filt: F): Filter<InpInfer<F>> { const wrapper = (inp: InpInfer<F>): boolean => filt(inp); return wrapper; }
修改后未指定具体Filter类型时,默认的参数类型为unknown,unknown & T的类型运算结果符合预期,不会出现never的问题。
内容的提问来源于stack exchange,提问作者Erik
相关产品推荐
相关产品推荐

