如何获得元组元组的扁平元组类型?

Ped*_*o A 5 tuples typescript recursive-type

考虑我有一个元组元组:

type Example = [[3,5,7], [4,9], [0,1,10,9]];
Run Code Online (Sandbox Code Playgroud)

我想创建一个实用程序类型Flatten<T>,以便Flatten<Example>提供:

type FlatExample = Flatten<Example>;
// type FlatExample = [3,5,7,4,9,0,1,10,9];
Run Code Online (Sandbox Code Playgroud)

对于我的用例,您可以假设元组仅嵌套一层。元组可以有任何大小。

我怎样才能做到这一点?

Tit*_*mir 7

为此,您需要递归条件类型。这将在 4.1 中得到完全支持:

type Example = [[3,5,7], [4,9], [0,1,10,9]];
type Flatten<T extends any[]> = 
    T extends [infer U, ...infer R] ? U extends any[] ? [...U, ... Flatten<R>]: []: []
type FlatExample = Flatten<Example>;
Run Code Online (Sandbox Code Playgroud)

游乐场链接

编辑

更简单的版本,对 jcalz 的支持:

type Example = [[3,5,7], [4,9], [0,1,10,9]];
type Flatten<T extends any[]> = 
    T extends [any, ...infer R] ? [...T[0], ... Flatten<R>]:  []
type FlatExample = Flatten<Example>;
Run Code Online (Sandbox Code Playgroud)

游乐场链接

/编辑

即使在今天,您也可以破解一个版本(需要额外的间接性来欺骗编译器以允许递归条件类型,从概念上讲,这等效于上面更简单的版本):

type Example = [[3, 5, 7], [4, 9], [0, 1, 10, 9]];
type Flatten<T extends any[]> = T extends [infer U, ...infer R] ? {
    1: U extends any[] ? [...U, ...Flatten<R>] : [],
    2: []
}[U extends any[] ? 1 : 2] : [];

type FlatExample = Flatten<Example>;

Run Code Online (Sandbox Code Playgroud)

游乐场链接

只是为了好玩,4.1,广义扁平化版本。

type Example = [[3,5,7], [4,9, [10, 12, [10, 12]]], [0,1,10,9, [10, 12]]];
type Flatten<T extends any[]> = 
    T extends [infer U, ...infer R] ? 
        U extends any[] ? 
        [...Flatten<U>, ... Flatten<R>]: [U, ... Flatten<R>]: []
type FlatExample = Flatten<Example>;
Run Code Online (Sandbox Code Playgroud)

游乐场链接

注意:虽然 4.1 更支持递归类型,但您仍然会遇到编译器硬编码限制,例如类型实例化深度和总类型实例(因为这样的递归类型会生成大量类型实例化)。所以请谨慎使用。