如何声明TypeScript元组的索引类型?
解决TypeScript元组索引类型的严格约束问题
你遇到的问题根源在于keyof typeof arr的范围太宽泛——它不仅包含元组的字面量索引"0"、"1",还涵盖了数组通用的number索引,以及数组原型上的所有属性(比如length、toString等)。所以当你给index赋值2时,TypeScript会将其匹配到number类型,而元组作为数组的子类型,允许number类型索引(尽管运行时会越界,但类型检查层面不会报错)。
要获取元组的精确数字索引类型(即0 | 1),可以自定义一个工具类型来提取元组的字面量索引并转换为数字类型:
// 自定义工具类型:提取元组的数字索引类型 type TupleIndices<T extends readonly any[]> = { [K in keyof T]: K extends `${infer N extends number}` ? N : never }[keyof T]; // 示例用法 const arr = [1, 2] as const; // 得到精确的索引类型:0 | 1 type ArrIndex = TupleIndices<typeof arr>; // 合法赋值 const validIndex: ArrIndex = 1; console.log(arr[validIndex]); // 正常输出2 // 非法赋值会触发类型报错 const invalidIndex: ArrIndex = 2; // 报错:Type '2' is not assignable to type '0 | 1'.ts(2322) console.log(arr[invalidIndex]);
也可以用更简洁的写法直接推导,不需要单独定义工具类型:
const arr = [1, 2] as const; type ArrIndex = Exclude<keyof typeof arr, keyof any[]> extends `${infer N extends number}` ? N : never; const index: ArrIndex = 2; // 同样会触发类型报错
原理说明
keyof typeof arr得到元组的所有键,包括字面量索引、通用number索引和数组原型属性;- 通过
Exclude<keyof typeof arr, keyof any[]>排除数组的通用属性,得到仅字面量索引"0" | "1"; - 再通过模板字符串类型将字符串索引转换为对应的数字字面量类型
0 | 1,实现严格的索引约束。
内容的提问来源于stack exchange,提问作者Ivan Rubinson
相关产品推荐
相关产品推荐

