TypeScript类型引用透明性异常与泛型类型推断问题咨询
核心原理前提
首先需要明确两个TypeScript泛型推断的基础规则:
- 条件类型(你实现的
Widen/WidenNS都属于递归条件类型)无法作为反向推断源:TS不能通过WidenNS<T> = 某个类型的结果,反向推导得到T的具体值,只能通过T的显式约束缩小范围。 - 泛型参数的推断优先级:显式传入的泛型 > 从调用参数直接推断的泛型 > 泛型默认值,默认值仅作为无推断结果时的 fallback,不会作为类型绑定规则。
问题1:FGood和FBad的行为差异原因
你的“引用透明性”预期不成立,本质是两类写法的泛型推断逻辑完全不同:
- FGood有两个独立的泛型推断位点:
T和W是两个独立泛型,W = WidenNS<T>只是默认值,没有绑定两者的关联。当你调用new FGood(6, x => x + 2)时,TS首先从构造参数直接推断出W = number,不需要和T产生关联;而T因为没有其他推断位点,会直接取其约束的上限值number | string,最终得到FGood<string | number, number>的类型。 - FBad只有一个泛型推断位点:没有独立的
W泛型,构造参数的类型是WidenNS<T>,属于依赖T的条件类型。按照前面的规则,TS不能通过WidenNS<T>兼容数字6的结果反向推导出T = number,只能取T的约束上限number | string,所以最终推断为FBad<string | number>。
问题2:FGood2和FBad2的T被推断为unknown的原因
这个现象是泛型无推断位点、无约束时的默认行为:
- 对于
FGood2,T没有加任何约束,也没有任何参数可以直接推断T的类型(W已经从参数直接推断为number,和默认值WidenNS<T>无关),所以TS直接将T推断为默认的unknown。 - 对于
FBad2,T同样没有约束,而构造参数的WidenNS<T>是条件类型,无法反向推导T的类型,TS找不到任何缩小T范围的依据,所以也会推断为unknown。
至于你疑惑的“为什么unknown没有导致FGood/FBad的T被推断为更宽的类型”,原因是FGood和FBad的T都加了extends Types的约束,Types本身就是number | string,T的范围被严格限制在这个联合类型内,不可能超出边界到unknown。
内容的提问来源于stack exchange,提问作者Kiuhnm
相关产品推荐
相关产品推荐

