TypeScript实现联合类型判断泛型时推导异常的解决方案
问题根因
初始代码结果不符合预期,本质是触发了TypeScript条件类型的分布式行为:
当extends前的泛型参数是「裸类型」(没有被元组、数组等类型包装)时,传入联合类型会被自动拆解,对每个成员单独做条件判断,最后把所有结果合并为联合类型返回。
以Selector<string | number>为例,实际计算过程是:
- 联合类型被拆为
string和number两个独立类型 - 分别计算:
string extends string得到'string',number extends string得到'primitive' - 结果合并为
'string' | 'primitive',和预期的'primitive'不一致。
实现方案
要满足需求需要做两处修正:
- 用元组包裹
extends两侧的类型,取消分布式判断,让TypeScript对整个联合类型做整体兼容性检查,而不是拆分判断 - 增加一层类型判断区分「字符串字面量联合」和「宽泛的string原始类型」:对于字符串字面量类型
T,string extends T永远不成立;只有当T是宽泛的string类型时,这个判断才成立。
最终可运行的代码如下:
type PrimitiveDataType = 'primitive'; type StringValue = 'string'; type Selector<T> = [T] extends [string] ? string extends T ? PrimitiveDataType : StringValue : PrimitiveDataType; // 用例验证 type StringCheck = Selector<'boo' | 'bar'>; // 推导出'string',符合预期 type PrimitiveCheck = Selector<string | number>; // 推导出'primitive',符合预期
边界场景覆盖
这个实现同时可以覆盖所有符合需求描述的边界情况:
- 单个字符串字面量:
Selector<'abc'>返回'string' - 宽泛string原始类型:
Selector<string>返回'primitive' - 非字符串原始类型联合:
Selector<number | boolean>返回'primitive' - 字符串字面量与宽泛string混合:
Selector<'abc' | string>返回'primitive'
内容的提问来源于stack exchange,提问作者cyrus-d
相关产品推荐
相关产品推荐

