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

问题描述:

我有这个

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

如何制作(压扁)

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

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

We can do that by mapped types. Consider the code:

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] 扩展 any[] ?T[K][0] : T[K] - 我们说如果给定键上元素的值是一个数组,那么给我这个数组的第一个元素的类型(索引 0),如果不要保持原样,因为没有什么可压扁的
  • [K in keyof T] - means we want to have all keys, so in tuple say elements
  • T[K] extends any[] ? T[K][0] : T[K] - we say if the value of the element on the given key is an array then give me a type of an first element of this array (index 0), if not leave it as is, as there is nothing to be flatten

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

If your tuples consider more then one type of the element, then above solution will take the first only. So for tuple [string, number] it will produce the string. If we want to gather all possible types inside the tuple we can create more sophisticated type. Consider:

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] 扩展 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] means that if our element is an array then get me types of all elements, but remove types of values in array prototype.
    • 在结果 Flatten> 中将产生 [string |号码].所以这取决于你的目标是什么.

      In the result Flatten<Params<[string, number]>> will produce [string | number]. So it depends what is your goal.

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

      The last proposition is, if you don't consider other types and only nested array/tuples, we can avoid conditional types. Consider last solution:

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

以上类型限制更多,因为它仅适用于 [[]] 但更简洁和具体.

Above type is more restrict as it works with only [[]] but is more concise and specific.