[TypeScript] Type Challenges #459 - Flatten

84 阅读1分钟

题目描述

在这个挑战中,你需要写一个接受数组的类型,并且返回扁平化的数组类型。

例如:

type flatten = Flatten<[1, 2, [3, 4], [[[5]]]]> // [1, 2, 3, 4, 5]

题解

// ============= Test Cases =============
import type { Equal, Expect } from './test-utils'

type cases = [
  Expect<Equal<Flatten<[]>, []>>,
  Expect<Equal<Flatten<[1, 2, 3, 4]>, [1, 2, 3, 4]>>,
  Expect<Equal<Flatten<[1, [2]]>, [1, 2]>>,
  Expect<Equal<Flatten<[1, 2, [3, 4], [[[5]]]]>, [1, 2, 3, 4, 5]>>,
  Expect<Equal<Flatten<[{ foo: 'bar'; 2: 10 }, 'foobar']>, [{ foo: 'bar'; 2: 10 }, 'foobar']>>,
]

// @ts-expect-error
type error = Flatten<'1'>


// ============= Your Code Here =============
type Flatten<T extends unknown[]> =
  T extends [infer Head, ...infer Tail]
      ? Head extends unknown[]
          ? [...Flatten<Head>, ...Flatten<Tail>]
          : [Head, ...Flatten<Tail>]
      : []

类型约束

  • T extends unknown[]:这个约束确保传入的类型参数T是一个数组

条件类型

  • T extends [infer Head, ...infer Tail]

    • 如果T不是一个空数组:

      • infer Head:将T的第一个元素类型推断为Head

      • ...infer Tail:将T的剩余元素类型推断为Tail

      • Head extends unknown[]

        • 如果Head是一个数组:

          • [...Flatten<Head>, ...Flatten<Tail>]:递归调用...Flatten<Head>...Flatten<Tail>,并将结果合并
        • 如果Head不是一个数组

          • [Head, ...Flatten<Tail>]:将Head放在返回结果的开头,并与...Flatten<Tail>的结果合并
    • 如果T是一个空数组:

      • 返回[]