【问题标题】:How to define an object type with dynamic keys in TypeScript?如何在 TypeScript 中使用动态键定义对象类型?
【发布时间】:2020-07-24 06:02:14
【问题描述】:

我有一个 const 对象,如下所示:

export const Language: Values = {
  es: {urlValue: 'es', label: 'Spain'},
  en: {urlValue: 'en', label: 'Anything'},
  eb: {urlValue: 'eb', label: 'Other thing'},
};

export interface Values {
  [name: string]: Value;
}

export interface Value {
  urlValue;
  label;
  selected?;
}

现在在应用程序的某个地方,我们读取了一些具有这种格式的数据,巧合的是,它们具有完全相同的键:

{
  es: 32,
  en: 11,
  eb: 56
}

所以实际上我需要另一个像这样的对象类型:

export class AnotherObject {

  constructor(public es: number,
              public en: number,
              public eb: number) {
  }
}

但是我是否也可以动态创建这种类型,以便它自动使用 Language 对象的键或“Value”类型的 urlValue?

PS:这个问题是我们确切用例的简化形式,其中我们有多个常量,例如 Languages。所以自动化会很有帮助。

编辑:对于@basarat 的建议 - 由于此对象是父对象的一部分,我实际上需要在此部分中定义类型:

export class ParentObject {
  thatObjectAbove: AnotherObject;
  otherObjects: ..
  ..
}

export interface AnotherObject {
  [name: LanguageOptions]: number;
}

我遇到错误“索引签名参数类型不能是联合类型。请考虑改用映射对象类型。”在“[名称:LanguageOptions]:数字;”行的“名称”部分

【问题讨论】:

    标签: typescript


    【解决方案1】:

    keyof type operator 将键名作为类型提供给您:

    export const Language = {
      es: {urlValue: 'es', label: 'Spain'},
      en: {urlValue: 'en', label: 'Anything'},
      eb: {urlValue: 'eb', label: 'Other thing'},
    };
    
    type LanguageOptions = keyof typeof Language; // 'es' | 'en' | 'eb'
    

    【讨论】:

    • 感谢您的回答。但是我在你使用 keyof 的最后一行有这个错误:'Language' 指的是一个值,但在这里被用作类型。
    • 已修复。你需要用typeof获取变量的类型,然后使用keyof获取类型的键。
    • 好的..但我仍然不能使用这个“类型”作为关键类型......我编辑了这个问题。
    【解决方案2】:

    继续this answer:

    我已经实现了我的目标,将 AnotherObject 定义为 type 而不是 interface。

    type LanguageOptions = keyof typeof Language;  // as from basarat's answer
    
    type AnotherObject = {[key in LanguageOptions]: number}; // is actually a type, still is named as 'object' so that it is still compatible with the question's code
        
    export class ParentObject {
      thatObjectAbove: AnotherObject;
      otherObjects: ..
      ..
    }
    

    正如here所说,这是因为打字稿的奇怪行为,可以通过这种方式修复。

    所以单线的最终解决方案:

    thatObjectAbove: {[key in keyof typeof Language]: number};
    

    thatObjectAbove: Record<keyof typeof Language, number>;  // Record is a built-in typescript type
    

    【讨论】:

      【解决方案3】:

      你能稍微修改一下你的代码吗?

      class DynamicClass<T> {
          constructor(values?: { [key in keyof T]?: T[key] }) {
              for (const key of Object.keys(values)) {
                  this[key] = values[key];
              }
          }
      }
      
      class MyClass extends DynamicClass<MyClass> {
          attr1: string;
          attB: number;
          obj: {
              wow: string,
              yeah: boolean
          };
      }
      
      
      new MyClass({
          attr1: 'a',
          obj: {
              wow: '',
              yeah: true
          },
          att
      })
      

      【讨论】:

        猜你喜欢
        • 2022-01-17
        • 2022-12-05
        • 1970-01-01
        • 1970-01-01
        • 2019-12-21
        • 2019-04-05
        • 2021-12-08
        • 2020-12-05
        • 2021-07-14
        相关资源
        最近更新 更多