为什么使用never类型作为数组索引器会返回数组值的联合类型
TypeScript 该行为的原理与设计意义
核心行为原理
你用到的A[never]属于TypeScript的索引访问类型,作用是提取类型A对应索引位置的所有可能值的类型,出现差异化推导结果的原因和两个变量的类型推导规则、never作为索引的特殊逻辑有关:
- 两个变量的基础类型差异
- 加了
as const声明的tuple,会被TypeScript推导为只读字面量元组类型:readonly ["1", "2"],它的合法索引是明确的联合类型0 | 1,两个索引对应的元素类型分别是字面量"1"和"2"。 - 未加限定的
array会被推导为可变普通数组类型:string[],它的合法索引是任意number类型,所有元素的统一类型为string。
- 加了
never作为索引的特殊规则never是TypeScript中所有类型的子类型,可以匹配所有可能的索引签名,当用never作为索引访问数组/元组类型时,TypeScript会返回该集合所有元素的类型联合,也就是把所有合法索引对应的类型合并为联合类型返回。
因此就会出现你看到的结果:
- 元组的元素类型为
"1" | "2",所以UninType被推导为该字面量联合 - 普通数组的元素类型均为
string,所以StringType被推导为string
该特性的设计意义
这个特性本质是TypeScript提供的便捷类型提取能力,在实际开发中价值很高:
- 可以直接从已有的常量数组/元组中提取元素类型,不需要重复定义,保证代码中类型和业务常量完全同步。比如你有一个存储业务枚举值的常量列表,就可以直接提取它的元素联合类型做参数校验,避免手动写类型出现和常量不一致的问题。
- 是实现通用泛型工具类型的基础能力,比如TS常用的工具类型
ElementType(用来提取数组元素类型)就可以用这个特性实现:type ElementType<T extends any[]> = T[number](日常开发中更常用T[number]做提取,和T[never]的效果在集合场景下是一致的)。 - 配合类型守卫、条件类型使用时,可以实现复杂的编译期类型校验,提前拦截不符合要求的入参,减少运行时错误。
内容的提问来源于stack exchange,提问作者Alexander Pankin
相关产品推荐
相关产品推荐

