打字稿将元组的元组类型转换为元组(展平元组)

时间:2019-12-18 12:59:05

标签: typescript typescript-typings typescript-generics

我有这个

Type T = Params<[Tuple1, Tuple2]> // eg [[string], [number]]

如何制作(展平)

Type Flatten<T> = Params<[string, number]> 

1 个答案:

答案 0 :(得分:2)

我们可以通过映射类型来做到这一点。考虑代码:

type T = Params<[Tuple1, Tuple2]>

// utility type
type Flatten<T extends any[]> = {
  [K in keyof T]: T[K] extends any[] ? T[K][0] : T[K]
}
type Result = Flatten<T>
// evaluates into [string, number]

const a: Result = ['a', 1] // correct value of the type

请注意Flatten的工作原理:

  • [K in keyof T]-表示我们要拥有所有键,因此在元组中说元素
  • T[K] extends any[] ? T[K][0] : T[K]-我们说如果给定键上的元素的值是一个数组,那么给我一种该数组的第一个元素的类型(索引0),如果不按原样保留它,那么没什么可扁平化的

如果元组考虑的元素多于一种,那么上述解决方案将只采用第一种。因此,对于元组[string, number],它将产生string。如果我们想在元组中收集所有可能的类型,我们可以创建更复杂的类型。考虑:

type Flatten<T extends any[]> = {
  [K in keyof T]: T[K] extends any[] ? T[K][Exclude<keyof T[K], keyof any[]>] : T[K]
}
  • T[K] extends any[] ? T[K][Exclude<keyof T[K], keyof any[]>] : T[K]意味着,如果我们的元素是数组,则可以获取所有元素的类型,但可以删除数组原型中的值的类型。

结果Flatten<Params<[string, number]>>将产生[string | number]。因此,这取决于您的目标。


最后一个命题是,如果您不考虑其他类型而仅考虑嵌套数组/元组,则可以避免条件类型。考虑最后一个解决方案:

type Flatten<T extends E[], E extends any[] = any[]> = {
  [K in keyof T]: T[K][Exclude<keyof T[K], keyof any[]>]
}

上述类型的限制更大,因为它仅与[[]]一起使用,但更加简洁和具体。