【问题标题】:TypeScript array with minimum length具有最小长度的 TypeScript 数组
【发布时间】:2018-09-29 08:32:22
【问题描述】:

如何在 TypeScript 中创建一个只接受包含两个或多个元素的数组的类型?

needsTwoOrMore(["onlyOne"]) // should have error
needsTwoOrMore(["one", "two"]) // should be allowed
needsTwoOrMore(["one", "two", "three"]) // should also be allowed

【问题讨论】:

    标签: typescript


    【解决方案1】:

    这可以通过以下类型来完成:

    type ArrayTwoOrMore<T> = {
        0: T
        1: T
    } & Array<T>
    
    declare function needsTwoOrMore(arg: ArrayTwoOrMore<string>): void
    
    needsTwoOrMore(["onlyOne"]) // has error
    needsTwoOrMore(["one", "two"]) // allowed
    needsTwoOrMore(["one", "two", "three"]) // also allowed
    

    TypeScript Playground Link

    【讨论】:

    • 你如何使用界面来做到这一点?说items: Item[] = [];,我需要至少1个Item
    • @ColdCerberus 没有区别。 Item[] 语法只是 Array&lt;Item&gt; 的糖。所以就像答案中的例子有ArrayTwoOrMore&lt;string&gt;你可以有ArrayTwoOrMore&lt;Item&gt;。要将其更改为 ArrayOneOrMore,只需复制 type ArrayTwoOrMore 定义并删除 1: T 行。
    • 虽然这种方法适用于数组声明,但当您使用 Array#map 将非空数组转换为其他内容时,TypeScript 将无法理解输出具有 0 键:Property '0' is missing in type 'MyType[]' but required in type '{ 0: MyType; }' .
    【解决方案2】:

    这是一个老问题,答案很好(它对我也有帮助),但我只是在玩游戏时偶然发现了这个解决方案。

    我已经定义了一个类型化元组 (type Tuple&lt;T&gt; = [T, T];),然后在其下方,我已经定义了两个或更多的数组,如上所述 (type ArrayOfTwoOrMore&lt;T&gt; = { 0: T, 1: T } &amp; T[];)。

    我突然想到尝试使用Tuple&lt;T&gt; 结构代替{ 0: T, 1: T },如下所示:

    type ArrayOfTwoOrMore&lt;T&gt; = [T, T, ...T[]];

    它奏效了。好的!它更简洁一些,在某些用例中可能更清晰。

    值得注意的是,一个元组必须是两个相同类型的项目。 ['hello', 2] 之类的东西是一个有效的元组。在我的小代码 sn-p 中,它恰好是一个合适的名称,它需要包含两个相同类型的元素。

    【讨论】:

      【解决方案3】:

      2021 年更新更短的符号:

      type arrMin1Str = [string, ...string[]]; // The minimum is 1 string.

      type arrMin2Strs = [string, string, ...string[]]; // The minimum is 2 strings.

      type arrMin3Strs = [string, string, string, ...string[]]; // The minimum is 3 strings.

      OR …等等

      这只是对@KPD 和@Steve Adams 答案的补充,因为所有指定的类型都是相同的。 这应该是自 TypeScript 3.0+ (2018) 以来的有效语法。

      【讨论】:

      • 不是最漂亮的,但就像一个魅力!
      【解决方案4】:

      扩展 Oleg 的答案,您还可以为任意最小长度的数组创建一个类型:

      type BuildArrayMinLength<
        T,
        N extends number,
        Current extends T[]
      > = Current['length'] extends N
        ? [...Current, ...T[]]
        : BuildArrayMinLength<T, N, [...Current, T]>;
      
      type ArrayMinLength<T, N extends number> = BuildArrayMinLength<T, N, []>;
      
      const bad: ArrayMinLength<number, 2> = [1]; // Type '[number]' is not assignable to type '[number, number, ...number[]]'.
      const good: ArrayMinLength<number, 2> = [1, 2];
      

      基于Crazy, Powerful TypeScript 4.1 Features

      【讨论】:

      • 这真的很酷——我没有意识到 TS 可以推断出这样的长度。它甚至可以知道你什么时候投错了——输入[1] as ArrayMinLength&lt;string, 4&gt;会给出一个非常清晰和正确的错误。
      【解决方案5】:
      type FixedTwoArray<T> = [T,T]
      interface TwoOrMoreArray<T> extends Array<T> {
          0: T
          1: T
      }
      
      let x: FixedTwoArray<number> = [1,2];
      let y: TwoOrMoreArray<string> = ['a','b','c'];
      
      

      TypeScript Playground

      【讨论】:

        猜你喜欢
        • 2020-10-13
        • 2023-01-30
        • 2016-06-16
        • 1970-01-01
        • 2012-10-22
        • 1970-01-01
        • 1970-01-01
        • 2020-09-24
        相关资源
        最近更新 更多