【问题标题】:Typescript: How to add an item to a tuple?打字稿:如何将项目添加到元组?
【发布时间】:2019-05-27 20:18:05
【问题描述】:

为什么会产生错误“A rest element type must be an array type.”?

type QWE<T extends [number, string]> = [boolean, ...T]
                                                 ^^^^ the error is here

【问题讨论】:

  • 我猜这与T 的通用性有关,因为即使T extends any[] 也会发出相同的错误。
  • 在 3.0 之前,我们不能将元组或泛型类型参数传播到函数,这必须实现。同样,rest in tuples 目前只支持数组,没有人实现将其他元组传播到给定元组的其余部分的能力
  • @TitianCernicova-Dragomir 我只是想请你回答,但对never 的回答分心了)无论如何,所以没有办法以某种方式修改元组?没有办法在元组的开头或结尾添加一些东西?附言我很高兴表示感谢并选择您的答案
  • 一开始可以通过将元组传播到一个函数并提取参数来完成,如果你愿意,我可以在答案中提供它。最后,我认为有一些不推荐的技巧涉及递归类型别名,但明确不推荐
  • @TitianCernicova-Dragomir 是的,我当然想要!尤其是因为我不太了解您所写的方法:) 提前致谢!

标签: typescript typescript-typings


【解决方案1】:

在 3.0 之前,我们不能将元组或泛型类型参数传播到函数,这必须实现。同样,元组中的其余部分目前仅支持数组,没有人实现将其他元组传播到给定元组的其余部分的能力,我猜要实现它需要大量的努力和复杂性。

要在另一个已知元组的末尾添加一个元组,我们可以使用将元组扩展为函数的能力,然后将参数类型提取为元组。

type ArgumentTypes<T extends (...a: any) => any> =
    T extends (...a: infer A) => any ? A : never;
type QWE<T extends [number, string]> = 
    ArgumentTypes<(a: boolean, ...r: T) => void>

type R = QWE<[number, string]>

在开始时添加元组更有问题,我相信有一些非常不推荐的黑客可以使用递归类型别名来实现这一点。你也可以定义多个条件来支持一个元组中的多个元素,但如果可能的话我会避免它

【讨论】:

  • 仅供参考,有内置的辅助类型Parameters&lt;T&gt;,因此您可以使用它而不是定义ArgumentTypes
  • @AlekseyL。 10x 我想知道为什么 lib.d.ts 中没有类似的东西,我想我只是错过了 :)
【解决方案2】:

如果有人觉得它有用,这是提香类型的一个版本,在更多情况下有所改进:

type R = TupleUnshift<boolean, [number, string]> // [boolean, number, string]


type TupleUnshift<A, B extends [...any[]]> = ((a: A, ...r: ForcedTuple<B>) => void) extends (...a: infer R) => any ? R : never

type ForcedTuple<T> =
    T extends [
        infer A,
        infer B,
        infer C,
        infer D,
        infer E,
        infer F,
        infer G,
        infer H,
        infer I,
        infer J,
        infer K,
        infer L,
        infer M,
        infer N,
        infer O,
        infer P,
        infer Q,
        infer R,
        infer S,
        infer T,
        infer U,
        infer V,
        infer W,
        infer X,
        infer Y,
        infer Z
    ]
    ?
    [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z]
    : T

【讨论】:

    【解决方案3】:

    使用 TypeScript 4.0 variadic tuple types,将项目 I 添加到元组类型 T 变得更加容易:

    type Prepend<I, T extends unknown[]> = [I, ...T]
    type Append<I, T extends unknown[]> = [...T, I]
    type AddBetween<I, T extends unknown[], U extends unknown[]> = [...T, I, ...U]
    
    type PrependTest = Prepend<boolean, [string, number]> 
    // [boolean, string, number]
    
    type AppendTest = Append<boolean, [string, number]> 
    // [string, number, boolean]
    
    type AddBetweenTest = AddBetween<boolean, [string], [number]> 
    // [string, boolean, number]
    

    Playground sample code

    【讨论】:

    • 很棒的类型,可惜使用后参数名称消失了
    • @ElSajko 您可以调整上述类型以处理仅限元组的参数类型,以便标记的元组元素可以提供参数名称。例如。 type Append&lt;I extends unknown[], T extends unknown[]&gt; = [...T, ...I]; type T1 = Append&lt;[qux: string], Param&gt;,见example
    猜你喜欢
    • 2018-08-18
    • 2020-12-22
    • 2021-10-27
    • 2018-06-10
    • 2021-07-30
    • 2023-01-07
    • 2021-08-25
    • 2021-08-30
    • 1970-01-01
    相关资源
    最近更新 更多