给出一个打字文本元组,例如:

const arr = [1, 2] as const;

我们在索引时进行静态类型判断:

console.log(arr[1]);

很好,但是

console.log(arr[2]);

以下方面的错误:

长度为"%2"的元组类型"Readonly[1,2]"在索引"%2"处没有元素.ts(2493)

这太棒了.


我想将一个常量声明为该元组的索引类型,以便可以分配给该常量的内容遵循相同的约束(0 | 1).

我试过这个:

const index: keyof typeof arr = 2 as const;
console.log(arr[index]);

但Typescript 没有显示任何错误.我怀疑indexnumber,这太宽了.

推荐答案

是的,不管出于什么原因,元组索引都是数字字符串literal types,如"0""1",而不是对应的numeric文字类型,如01.还有numberindex signature,所以keyof ["a", "b"]等于number | "0" | "1" | ....这意味着只要使用keyof,你就可以分配任何数字.

如果要计算数字文字,可以使用template literal types来计算,至少在TypeScrip 4.8和更高版本中是这样:

type TupleIndices<T extends readonly any[]> =
    Extract<keyof T, `${number}`> extends `${infer N extends number}` ? N : never;

首先,通过对可被解析为数字的所有字符串的集合`${number}`进行过滤,来从完整密钥集合中I Extract数字字符串文字类型.这就消除了number本身(它不是字符串)以及"length""slice"以及其他数组成员.所以我们有"0" | "1" | "2" | ...个.然后,我使用TypeScrip 4.8中引入的the improved infer types将这些字符串文字转换为数字文字.

这就给了你这个:

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

Playground link to code

Typescript相关问答推荐

如何使用属性作为具有Generics的TypScript类中的类型守护?

在Angular中,如何在文件上传后清除文件上传文本框

来自类型脚本中可选对象的关联联合类型

如何以Angular 形式显示验证错误消息

在Reaction-Native-ReAnimated中不存在Animated.Value

Fp-ts使用任务的最佳方法包装选项

垫表页脚角v15

剧作家元素发现,但继续显示为隐藏

@TANSTACK/REACT-QUERY中发生Mutations 后的数据刷新问题

如何在React组件中指定forwardRef是可选的?

如何将对象数组中的键映射到另一种对象类型的键?

是否可以强制静态方法将同一类型的对象返回其自己的类?

如何解决&Quot;类型不可分配给TypeScrip IF语句中的类型&Quot;?

如何创建一个将嵌套类属性的点表示法生成为字符串文字的类型?

TypeScript:方法获胜';t接受较窄类型作为参数

如何限定索引值必须与相应属性的id字段相同

如何使用 runInInjectionContext 中的参数测试功能性路由防护

类型为 `(callback: (...args: T) => void, params: T)` 的函数的泛型

如何解决 Angular 中的 ts(18048) 错误

使用useEffect和useCallback是多余的吗?