为什么TypeScript中infer对数组的首位匹配模式无法生效?
核心原因
你遇到的匹配差异本质是TypeScript对可变数组类型和固定长度元组类型的条件匹配规则不同导致的,具体拆解如下:
第一步:明确typeof myObject.foo的默认推导类型
在没有加as const或者显式元组标注的前提下,TypeScript会把对象里的数组字面量推导为可变的普通数组类型:
const myObject = { foo: ['a', 'b', 'c'] } // typeof myObject.foo 推导结果为 string[],不是 ['a','b','c'] 固定长度元组
string[]的长度是通用的number类型,TypeScript无法确定它的实际长度,也无法保证它一定包含至少1个元素(你后续完全可以执行myObject.foo = []赋值为空数组,完全符合类型规则)。
第二步:两种匹配模式的规则差异
第一种模式 [...infer Content]
这个带剩余展开的匹配模式可以兼容任意长度的数组:不管是长度为0的空数组、长度不确定的可变数组、还是固定长度的元组,...都可以匹配全部元素,因此string[] extends [...infer Content]的判断结果为真,MyType推导为string。
第二种模式 [infer First, ...infer Tail]
这个模式要求被匹配的类型必须至少包含1个元素:TypeScript需要明确知道目标数组的长度≥1才会判定匹配成立。而string[]的长度不确定,无法满足这个前提,因此条件判断结果为假,MyType推导为boolean。
验证方案
如果你想让第二种模式也匹配成功,只需要把foo的类型锁定为固定长度的元组即可,比如加as const断言:
const myObject = { foo: ['a', 'b', 'c'] as const } // 此时typeof myObject.foo 是 readonly ["a", "b", "c"],固定长度为3 type MyType = typeof myObject.foo extends [infer First, ...infer Tail] ? string : boolean // MyType 会正确推导为 string
内容的提问来源于stack exchange,提问作者johann1301s
相关产品推荐
相关产品推荐

