如何在TypeScript中使用动态键定义对象类型?

如何在TypeScript中使用动态键定义对象类型?,typescript,Typescript,我有一个常量对象,看起来像这样: 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 inter

我有一个常量对象,看起来像这样:

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?;
}
export class AnotherObject {

  constructor(public es: number,
              public en: number,
              public eb: number) {
  }
}
现在,在应用程序的某个地方,我们读取了一些具有这种格式的数据,这些数据碰巧具有完全相同的键:

{
  es: 32,
  en: 11,
  eb: 56
}
所以实际上我需要另一种像这样的对象类型:

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?;
}
export class AnotherObject {

  constructor(public es: number,
              public en: number,
              public eb: number) {
  }
}
但是我是否可以动态创建这个类型,以便它自动使用Language对象的键,或者“Value”类型的urlValue

PS:问题是我们确切用例的简化形式,我们有多个类似常量的语言。所以一个自动系统会很有帮助

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

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

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

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

< p>它给出了键名的类型:

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'

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

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
})
类动态类{
构造函数(值?:{[key-in-keyof-T]?:T[key]}){
for(对象的常量键。键(值)){
此[键]=值[键];
}
}
}
类MyClass扩展了DynamicClass{
属性1:字符串;
附件B:编号;
obj:{
哇:绳子,
是的:布尔
};
}
新MyClass({
属性1:‘a’,
obj:{
哇:'',
是的,没错
},
att
})
继续:

我已经实现了将另一个对象定义为类型而不是接口的目标

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: ..
  ..
}
如前所述,这是因为typescript的奇怪行为,可以用这种方式修复

因此,一个衬里中的最终解决方案:

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

thatObjectUpper:Record;//记录是内置的类型脚本类型

谢谢你的回答。但我在最后一行中有一个错误,您使用keyof:“Language”指的是一个值,但在这里被用作类型。已修复。您需要使用
typeof
获取变量的类型,然后使用
keyof
获取类型的键。确定。。但我还是不能用这个“类型”作为键类型。。。我编辑了这个问题。