【问题标题】:How to define array typescript interface with optional unique strings?如何使用可选的唯一字符串定义数组打字稿接口?
【发布时间】:2020-09-04 12:55:08
【问题描述】:

我想定义一个带有可选字符串值的接口。比如:

interface IEntity {
    values: ['RemainingUnits', 'ActualUnits', 'PlannedUnits']
}

但是使用这个界面我有问题:

const entity0: IEntity = { values: ['PlannedUnits'] }; // => Error
const entity1: IEntity = { values: ['RemainingUnits', 'ActualUnits'] }; // => Error
const entity2: IEntity = { values: ['PlannedUnits', 'RemainingUnits', 'ActualUnits'] }; // => Error

那么有没有办法写出正确的接口来避免上面的错误呢?

而且完全没有重复的字符串且不为空

【问题讨论】:

标签: typescript typescript-typings


【解决方案1】:

也许:

type Units = 'RemainingUnits' | 'ActualUnits' | 'PlannedUnits';

interface IEntity {
  values?: Units[];
}

【讨论】:

    【解决方案2】:

    您可以尝试对特定字符串使用<>

    interface IEntity {
        values: Array<'RemainingUnits' | 'ActualUnits' | 'PlannedUnits'>
    }
    

    此外,受 Nenroz 的启发,我认为您也可以使用 type 对字符串进行分组。当你有许多不同的东西时很好用。

    type Units = 'RemainingUnits' | 'ActualUnits' | 'PlannedUnits';
    
    interface IEntity {
      values: Array<Units> ;
    }
    

    【讨论】:

    • 不推荐使用语法Array&lt;&gt;。 Typescript 建议使用括号Units[]
    • 真的吗?有参考资料吗?
    • 好吧,我的评论是基于 TS 编译器的建议。这是关于 readonly 的东西,它只允许使用括号语法。您可以在 [这里] (typescriptlang.org/docs/handbook/release-notes/…) 阅读此内容
    • 感谢您的材料。我之前没有意识到:)
    【解决方案3】:

    我认为这不是类型系统的用途。通过将此作为编译时规则强制执行(这是所有 Typescript 的类型),您可以确保 Typescript 只允许它可以在编译时完全确定的值。这将不允许对数组进行就地修改,即使是符合您规则的数组。此接口的可用性成本可能会超过它为您的 API 消费者提供的错误捕获价值。

    let array: Units = ['RemainingUnits'];
    if (condition) {
      array.push('ActualUnits');  // not allowed; Typescript can't reason about it
    }
    return array;
    

    此外,Javascript 有一些有效的方法来强制执行非重复行为(集合或对象键),这对于您想要的非常自然,并且还允许用户想要的运行时行为(例如能够修改列表在传递之前)。

    type Units = {
      RemainingUnits: boolean,
      ActualUnits: boolean,
      PlannedUnits: boolean
    }
    

    如果你真的想要这个,你需要把它拼出来:

    type A = 'RemainingUnits';
    type B = 'ActualUnits';
    type C = 'PlannedUnits';
    
    type Units = [A] | [B] | [C]
      | [A, B] | [A, C] | [B, A] | [B, C] | [C, A] | [C, B]
      | [A, B, C] | [A, C, B] | [B, A, C] | [B, C, A] | [C, A, B] | [C, B, A];
    
    interface IEntity {
      values: Units;
    }
    
    const example1: IEntity = { values: ['RemainingUnits', 'PlannedUnits'] }
    const example2: IEntity = { values: ['RemainingUnits', 'RemainingUnits'] }  //error
    const example3: IEntity = { values: [] }  //error
    

    typescript playground

    【讨论】:

      【解决方案4】:

      它应该适合你的情况:

      type Units = 'RemainingUnits' | 'ActualUnits' | 'PlannedUnits';
      
      interface IEntity {
          values: [Units, Units?, Units?]
      }
      
      const entity0: IEntity = { values: ['PlannedUnits'] }; // success
      const entity1: IEntity = { values: ['RemainingUnits', 'ActualUnits'] }; // success
      const entity2: IEntity = { values: ['PlannedUnits', 'RemainingUnits', 'ActualUnits'] }; // success
      

      【讨论】:

      • 字段不重复怎么办? :)
      • @zemil 很好看!没想到
      猜你喜欢
      • 2015-05-16
      • 2019-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-05
      • 2016-05-28
      • 2022-09-27
      相关资源
      最近更新 更多