如何将通用 rest 元素与元组类型一起使用?

How to use generic rest element with tuple types?

TypeScript 给我一个通用元组剩余元素的错误

type Tuple<Value extends any[]> = [...Value];

错误:

$ tsc
src/index.ts:1:36 - error TS2574: A rest element type must be an array type.

1 type Tuple<Value extends any[]> = [...Value];

我在这里错过了什么?


type Tuple<HEAD, TAIL extends any[]> = [HEAD, ...TAIL];

不工作,虽然这个工作:

type Tuple<Value extends any[]> = [...any[]];

更新 TS4.0+。 TypeScript 4.0 引入了对 variadic tuple types 的支持,所以这个问题中的代码应该可以像写的那样工作,而不需要根据函数参数改写你的操作。万岁!


TS3.9- 答案:

你唯一缺少的是这样的推断 isn't currently supported. Maybe it will be in a future version of TypeScript. Luckily there is still a way to do what you want by expressing the desired operation in terms of one on function parameters,因为从 TypeScript 3.0 开始,有一种方法可以在 tuple/array 类型和函数参数之间进行转换,你可以使用 infer 根据参数类型的需要。

这是 Tail 的一种可能实现:

type Tail<T extends any[]> = 
  ((...t: T) => void) extends ((x: any, ...u: infer U) => void) ? U : never;

type TestTail = Tail<[1,2,3,4]>; // [2,3,4]

请注意,您采用 tuple/array 类型 T,将其扩展到参数列表,然后将第一个参数之后的所有内容推断为另一个 tuple/array 剩余类型。

同样,您可以按照我称之为 Cons:

的方式实现 Tuple
type Cons<H, T extends any[]> = 
  ((h: H, ...t: T) => void) extends ((...u: infer U) => void) ? U : never;

type TestCons = Cons<string, [number, boolean]>; // [string, number, boolean]

我会把 Head 留给你作为练习(这是人们在想要显得聪明而不是懒惰时所说的话)。

无论如何,希望能帮助你取得进步。祝你好运!