【问题标题】:Implicitly create a tuple in Typescript在 Typescript 中隐式创建一个元组
【发布时间】:2022-02-20 01:21:27
【问题描述】:

有没有没有类型提示的方法在 Typescript 中创建元组。

如果我只是这样做

const tuple = [1, 2];

元组number[]的类型

我能到达的最接近单线的是

const tuple: [number, number] = [1, 2];

我错过了什么,还是这是唯一的方法?

【问题讨论】:

  • 您的解决方案不适用于数组的任何间接更改,例如tuple.push(123)
  • @Jay tuple 本身就是一个类型,如果你声明[number, number] 那么你只能在数组中压入数字类型。将数组声明为元组的目的是限制已知的一个或多个数组元素的类型。
  • 我知道的唯一方法是使用函数,这个答案最接近解决方案stackoverflow.com/questions/48872328/…
  • @TitianCernicova-Dragomir 的答案很棒。关键是打字稿无法推断元组:(请随意在此处添加此答案,我可以接受,因为我的问题不同

标签: typescript


【解决方案1】:

使用 typescript 3.0,您可以拥有自己的实用功能:

const tuple = <T extends any[]>(...args: T): T => args

并以这种方式使用它:

const tup = tuple(1, 2) // tup type is [number, number]

【讨论】:

  • 这不适用于已经创建的数组:tsplay.dev/w62avw
  • @ShaneCallanan 构造初始数组后类型信息已经丢失,打字稿无法神奇地取回数组长度,这在元组中是必需的。最好的 typescript 可以使用它知道的类型信息 (string[]) 来生成 [...string],它实际上是一个字符串数组
【解决方案2】:

Typescript 不会从数组字面量推断元组类型。你可以像你一样显式地指定类型,或者你可以创建一个辅助函数来使它更容易一些,并且仍然可以得到一些推断。

const tuple = <T extends [any] | any[]>(args: T): T => args
tuple(["A", "B"]) // [string, string]

编辑

从 3.4 开始,您还可以使用 as const 断言。这确实具有不需要额外函数的优点,但它会生成一个只读元组:

var t = [1, ''] as const;
t[0] = 1  //err

从 3.0 开始你还可以在 rest 参数中使用元组来推断元组:

const tuple = <T extends any[]>(...args: T): T => args
tuple("A", "B") // [string, string]

【讨论】:

  • 感谢您提供详细信息。希望将来至少我们可以使用variadic kinds 来避免显式声明许多函数
  • @Jay 我梦想着可变参数;)
  • 有没有办法做as const 断言返回可变元组?像[Number()] as MutableConst 这样的东西给[number] 而不是readonly [number]
  • 把link留在这里,以防有人在搜索T extends [any] | any[]的官方文档...
  • &lt;T extends [] | any[]&gt; 和 &lt;T extends [] | {}&gt; 更短,也可以工作。
【解决方案3】:

TypeScript 4.0 还有一种隐式推断元组类型的方法:

[...T] 类型,其中T 是类似数组的类型参数,可以方便地用于指示对元组类型推断的偏好[:] (docs)

const tuple = <T extends unknown[]>(args: [...T]): T => args
tuple(["A", "B"]) // [string, string]

Playground

【讨论】:

    【解决方案4】:

    从 TypeScript 3.4 开始,您可以在末尾简单地添加 as const。

    const tuple = [1, 2] as const;
    

    完全归功于 @bela53 的回答,它有一个更好的例子和 TS 操场的链接。

    【讨论】:

      【解决方案5】:

      我添加此答案以供参考,因为我发现 as const 创建只读元组并且其他技术扩大了值的类型很痛苦

      const tuple = <T extends any[]>(xs: readonly [...T]): T => xs as T;
      

      有两种使用方式:

      const a = tuple(['foo', 10] as const)
      

      a 是 ["foo", 10] 类型,不是只读的,typeof a[number] 是 "foo" | 10


      const b = tuple(['foo', 10]);
      

      b 是 [string, number] 类型,typeof b[number] 是 string | number

      【讨论】:

        猜你喜欢
        • 2019-09-20
        • 1970-01-01
        • 1970-01-01
        • 2022-01-23
        • 1970-01-01
        • 1970-01-01
        • 2015-12-20
        • 2013-09-10
        • 1970-01-01
        相关资源
        最近更新 更多