在TypeScript中有没有办法子集化一个元组并获取ith and (i - 1)th元素?
也就是说,类似于:
type A = [string, number, symbol, boolean];
type B<T extends any[], U extends keyof T> = [T[U - 1], T[U]] // Here T[U - 1] is not valid TS ofc;
type C = B<A, 2> // [number, symbol];
在TypeScript中有没有办法子集化一个元组并获取ith and (i - 1)th元素?
也就是说,类似于:
type A = [string, number, symbol, boolean];
type B<T extends any[], U extends keyof T> = [T[U - 1], T[U]] // Here T[U - 1] is not valid TS ofc;
type C = B<A, 2> // [number, symbol];
这里不需要递归的最简单方法是认识到对于元组T
,T
的第U-1
个元素与[undefined, ...T]
的第U
个元素相同,使用variadic tuple type将undefined
添加到元组T
的前面.undefined
的用法有些主观;我之所以 Select 它,是因为一般说来,arr[-1]
等于undefined
.但这取决于您的用例,应该做什么才是正确的.
从概念上讲,你会想要写
type B<T extends any[], U extends keyof T> =
[[undefined, ...T][U], T[U]];
但是类型判断器不理解U
绝对是泛型T
的索引[undefined, ...T]
.它不能执行更高阶的推理,即"较长的元组拥有较短元组的所有索引".因此,我们必须说服它以某种方式允许索引.一种方法是引入conditional判断,如果已知存在密钥,该判断将执行索引:
type Idx<T, K> = K extends keyof T ? T[K] : never;
这会给你带来:
type B<T extends any[], U extends keyof T> =
[Idx<[undefined, ...T], U>, T[U]];
让我们来测试一下:
type A = [string, number, symbol, boolean];
type C = B<A, 2> // [number, symbol];
type Q = B<A, 0> // [undefined, string]
type R = B<A, 100>; // [undefined, undefined]
看起来不错 同样,这取决于您的用例,当索引超出边界或在边缘时,您希望看到什么.但希望你能调整它以满足你的需要.