给定一个 TypeScript 元组,例如:
const arr = [1, 2] as const;
Run Code Online (Sandbox Code Playgroud)
我们对索引进行静态类型检查:
console.log(arr[1]);
Run Code Online (Sandbox Code Playgroud)
很好,但是
console.log(arr[2]);
Run Code Online (Sandbox Code Playgroud)
错误:
长度为“2”的元组类型“readonly [1, 2]”在索引“2”处没有元素。ts (2493)
这太棒了。
我想声明一个常量为该元组索引的类型,以便分配给该常量的内容遵循相同的约束(0 | 1)。
我试过这个:
const index: keyof typeof arr = 2 as const;
console.log(arr[index]);
Run Code Online (Sandbox Code Playgroud)
但 TypeScript 没有显示任何错误。我怀疑这个index范围number太宽泛了。
是的,无论出于何种原因,元组索引都是数字字符串文字类型,例如"0"和 ,"1"而不是相应的数字文字类型,例如0和1。还有一个number 索引签名,所以keyof ["a", "b"]会给你number | "0" | "1" | ...。这意味着只需使用keyof即可让您分配任何数字。
如果要计算数字文字,可以使用模板文字类型来执行此操作,至少在 TypeScript 4.8 及更高版本中:
type TupleIndices<T extends readonly any[]> =
Extract<keyof T, `${number}`> extends `${infer N extends number}` ? N : never;
Run Code Online (Sandbox Code Playgroud)
首先,我Extract通过过滤从完整键集中获取数字字符串文字类型`${number}`,即可以解析为数字的所有字符串的集合。这会消除number自身(不是字符串)以及"length"and"slice"和其他数组成员。这给了我们"0" | "1" | "2" | .... 然后,我使用TypeScript 4.8 中引入的改进infer类型将这些字符串文字转换为数字文字。
这给了你这个:
const arr = [1, 2] as const;
type ArrIndices = TupleIndices<typeof arr>;
// type ArrIndices = 0 | 1
type Also = TupleIndices<[9, 9, 9, 9, 9, 9, 9, 9, 9, 9]>;
// type Also = 0 | 1 | 2 | 9 | 3 | 4 | 5 | 6 | 7 | 8
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1021 次 |
| 最近记录: |