打字稿:从元组类型中删除条目

Typescript: Remove entries from tuple type

不确定这是否可行,但我希望能够定义一个类型,将元组转换为:[number, string, undefined, number][number, string, number](即过滤掉undefined)。

我想过这样的事情:

1
2
3
type FilterUndefined<T extends any[]> = {
    [i in keyof T]: T[i] extends undefined ? /* nothing? */ : T[i];
}

可悲的是,我很确定没有办法实现这一目标。


得到它了! 但它需要很多递归魔法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
type PrependTuple<A, T extends Array> =
  A extends undefined ? T :
  (((a: A, ...b: T) => void) extends (...a: infer I) => void ? I : [])

type RemoveFirstFromTuple<T extends any[]> =
  T['length'] extends 0 ? undefined :
  (((...b: T) => void) extends (a, ...b: infer I) => void ? I : [])

type FirstFromTuple<T extends any[]> =
  T['length'] extends 0 ? undefined : T[0]

type NumberToTuple<N extends number, L extends Array = []> = {
  true: L;
  false: NumberToTuple<N, PrependTuple<1, L>>;
}[L['length'] extends N ?"true" :"false"];

type Decrease<I extends number> = RemoveFirstFromTuple<NumberToTuple>['length']
type H = Decrease<4>

type Iter<N extends number, Items extends any[], L extends Array = []> = {
  true: L;
  false: Iter<FirstFromTuple<Items> extends undefined ? Decrease<N> : N, RemoveFirstFromTuple<Items>, PrependTuple<FirstFromTuple<Items>, L>>;
}[L["length"] extends N ?"true" :"false"];

type FilterUndefined<T extends any[]> = Iter<T['length'], T>
type I = [number, string, undefined, number];
type R = FilterUndefined

操场

这个怎么运作:

PrependToTuple是util,它取项A并列出T,并在A未定义时将其添加到第一位。 PrependToTuple => []PrependToTuple => [number]

RemoveFirstFromTuple以相同的方式工作

NumberToTuple以递归方式检查最终元组的长度是否为N,if
不是他给递归调用添加1。 创建Decrease util需要此util。

最重要的z Iter就像递归循环一样,当最终元组的长度为N(Input的大小)时,它的返回值Output,但当我们尝试添加PrependToTuple不会增加长度 >,所以当Iter extends undefined我们必须减少N.