Skip to content

FlattenDepth

约 589 字大约 2 分钟

2022-12-01

题目

递归地将数组扁平化,最多进行 depth 次。

type a = FlattenDepth<[1, 2, [3, 4], [[[5]]]], 2> // [1, 2, 3, 4, [5]]. 展开 2 次
type b = FlattenDepth<[1, 2, [3, 4], [[[5]]]]> // [1, 2, 3, 4, [[5]]]. 深度默认为 1

如果提供了深度,则保证其为正整数。

解题思路

我们已经在 Flatten 这个挑战中知道应该如何将一个数组完全扁平化。

type Flatten<T extends unknown[]> = T extends [infer F, ...infer R]
  ? F extends unknown[]
    ? [...Flatten<F>, ...Flatten<R>]
    : [F, ...Flatten<R>]
  : T

同样的思路可以应用到这个挑战多,只是多了一个限制条件,即最多进行 depth 次。

在 类型参数中添加一个 Depth 类型参数,表示最大次数。由于在 Typescript 中并不支持运算操作, 但我们可以通过给 元组添加成员,再获取元组的长度 来实现累加,添加一个 R 类型参数保存元组:

type FlattenDepth<
  T extends unknown[],
  Depth extends number = 1,
  R extends unknown[] = []
> = T extends [infer F, ...infer O]
  ? F extends unknown[]
    ? [...FlattenDepth<F, Depth, R>, ...FlattenDepth<O, Depth, R>]
  //     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  //     实际只在这里进行一次展开
    : [F, ...FlattenDepth<O, Depth, R>]
  : T

我们只需要在实际展开的位置,在类型参数 R 中添加成员,通过 R['length'] 获取最新长度, 判断是否达到 Depth 的最大限制。

答案

type FlattenDepth<
  T extends unknown[],
  Depth extends number = 1,
  R extends unknown[] = []
> = R['length'] extends Depth
  ? T
  : T extends [infer F, ...infer O]
    ? F extends unknown[]
      ? [...FlattenDepth<F, Depth, [unknown, ...R]>, ...FlattenDepth<O, Depth, R>]
      : [F, ...FlattenDepth<O, Depth, R>]
    : T

验证

type 
cases
= [
Expect
<
Equal
<
FlattenDepth
<[]>, []>>,
Expect
<
Equal
<
FlattenDepth
<[1, 2, 3, 4]>, [1, 2, 3, 4]>>,
Expect
<
Equal
<
FlattenDepth
<[1, [2]]>, [1, 2]>>,
Expect
<
Equal
<
FlattenDepth
<[1, 2, [3, 4], [[[5]]]], 2>, [1, 2, 3, 4, [5]]>>,
Expect
<
Equal
<
FlattenDepth
<[1, 2, [3, 4], [[[5]]]]>, [1, 2, 3, 4, [[5]]]>>,
Expect
<
Equal
<
FlattenDepth
<[1, [2, [3, [4, [5]]]]], 3>, [1, 2, 3, 4, [5]]>>,
Expect
<
Equal
<
FlattenDepth
<[1, [2, [3, [4, [5]]]]], 19260817>, [1, 2, 3, 4, 5]>>,
]

参考