TypeScript枚举转换为对象数组

247

我有一个这样定义的枚举:

export enum GoalProgressMeasurements {
    Percentage = 1,
    Numeric_Target = 2,
    Completed_Tasks = 3,
    Average_Milestone_Progress = 4,
    Not_Measured = 5
}

但我希望它以以下方式从我们的API表示为对象数组/列表:

[{id: 1, name: 'Percentage'}, 
 {id: 2, name: 'Numeric Target'},
 {id: 3, name: 'Completed Tasks'},
 {id: 4, name: 'Average Milestone Progress'},
 {id: 5, name: 'Not Measured'}]

有没有一种简单且本地化的方法来实现这个问题,或者我必须构建一个函数,将枚举类型转换为int和字符串,并将对象构建成数组?

有没有一种简单且本地化的方法来实现这个问题,或者我必须构建一个函数,将枚举类型转换为int和字符串,并将对象构建成数组?


枚举是在运行时存在的真实对象。因此,您可以通过执行以下操作来反转映射:GoalProgressMeasurements[GoalProgressMeasurements.Completed_Tasks] 以获取枚举名称。我不知道这是否有帮助。 - Diullei
你能更好地描述一下“来自我们的API”吗?可以举个使用的例子吗? - gilamran
31个回答

8

只需一行:

Object.entries(GoalProgressMeasurements).map(([key, value]) => ({id: key, value: value}))

无法通过此链接进行测试枚举类型 LAST_NUMBER_OF_TIME { LAST_60_DAYS = 60, LAST_30_DAYS = 30, LAST_15_DAYS = 15, LAST_1_WEEK = 7, LAST_1_DAY = 1, } Object.entries(LAST_NUMBER_OF_TIME).map(([key, value]) => ({id: key, value: value})) - hafiz ali
@hafizali,出了什么错误? - Roman Kostetskyi
你会得到一个由键和值组合而成的数组嵌套数组,对于大小为3的数组,总共将有6个项目。 - hafiz ali

4

另一种方法是使用ES8 Object.entries

export enum Weeks {  
    MONDAY = 1,  
    TUESDAY= 2,  
    WEDNESDAY = 3,  
    THURSDAY = 4,  
    FRIDAY = 5,  
    SATURDAY=6,  
    SUNDAY=7,  
}


function convertEnumToArray(){
   const arrayObjects = []            
     // Retrieve key and values using Object.entries() method. 
     for (const [propertyKey, propertyValue] of Object.entries(Weeks)) { 

      // Ignore keys that are not numbers
      if (!Number.isNaN(Number(propertyKey))) {  
        continue;  
      }  

      // Add keys and values to array
      arrayObjects.push({ id: propertyValue, name: propertyKey });  
    }        

  console.log(arrayObjects); 
}

将产生以下结果:
[ 
  { id: 1, name: 'MONDAY' },  
  { id: 2, name: 'TUESDAY' },  
  { id: 3, name: 'WEDNESDAY' },  
  { id: 4, name: 'THURSDAY' },  
  { id: 5, name: 'FRIDAY' },  
  { id: 6, name: 'SATURDAY' },  
  { id: 7, name: 'SUNDAY' } 
] 

不要脸地从这个博客偷了过来


4

首先我们获取该枚举的键数组。然后,使用map()函数将数据转换为所需的格式。id从键中获取,名称从相同的键的枚举中获取。

const converted = Object.keys(GoalProgressMeasurements).map(key => {
        return {
            id: GoalProgressMeasurements[key],
            name: key,
        };
    });

3
欢迎来到Stack Overflow。在回答问题时,解释你的代码片段的作用是个好主意。欲了解更多信息,请参见这里:[答案链接] - Djensen
1
以下是如何撰写出色答案的几个提示:https://stackoverflow.com/help/how-to-answer - Willie Cheng
请考虑在您的答案中添加一些解释或细节。虽然它可能回答了问题,但仅仅添加一段代码作为答案,并不能帮助提问者或未来的社区成员理解问题或所提出的解决方案。 - Maxim

3

我希望您不要在需要枚举条目列表的情况下使用TS Enums。

在运行时,枚举被实现为对象,但仅在以下情况下才按您期望的方式工作:

enum X {
  Z = 'z',
  F = 'f'
};

console.log(Object.values(X))
console.log(Object.keys(X))
>>>
[LOG]: ["z", "f"] 
[LOG]: ["Z", "F"] 

在这种情况下,它使用一个陷阱(TS允许您通过其数字值访问值):
enum X {
  Z,
  F
};

console.log(Object.values(X))
console.log(Object.keys(X))
>>>
[LOG]: ["Z", "F", 0, 1] 
[LOG]: ["0", "1", "Z", "F"] 

任何你编写的用于循环枚举的函数都将根据枚举定义工作/失败。这...不太好。
我的结论:枚举不是为了被用作对象而设计的。如果需要访问键和值集合,请使用const代替enum:
const Enumed = {
    X: 1,
    Y: 2
}

Typescript将控制对象键的存在性,并且您可以以安全和一致的方式执行Object.keys等操作。


3
export function enumKeys(E: any): string[] {
    return Object.keys(E).filter(k => isNaN(Number(k)));
}

export function enumValues(E: any): string[] | number[] {
    return enumKeys(E).map(k => E[k as any]);
}

适用于以下两种情况:

enum TestA {
    RED = "red",
    BLUE = "blue"
}

enum TestB {
    ONE = 1,
    TWO = 2
}

2
我已经解决了,方法如下。 假设你有一个像下面这样的枚举。
export enum UnitEnum {
  GRAM = 'gm',
  KILOGRAM = 'kg',
  LITRE = 'lt',
  CENTIMETER = 'cm',
  INCH = 'in',
  METER = 'mt',
  KILOMETER = 'km',
}

而且,你有一个像这样的类:

export interface Unit {
  Name: string;
  Symbol: string;
}

然后,您可以创建一个函数,如下所示,将异构枚举映射到特定类型的对象:

export function getDefaultUnits() {
  const myUnits = Object.entries(UnitEnum).map(x => {
    return { Name: x[0], Symbol: x[1] } as Unit
  })

  console.log(myUnits);

  return myUnits;
}

2

我只学了几个月的Typescript,下面的解决方案适用于我。希望它也能帮助其他人 -

export enum ScheduleType {
  Basic = <any>'B',
  Consolidated = <any>'C',
}

scheduleTypes = Object.keys(ScheduleType)
.filter((k, i) => i % 2)
.map((key: any) => {
  return {
    systemValue: key,
    displayValue: ScheduleType[key],
  };
});

它给出了以下结果 - [{displayValue: "基础", systemValue: "B"}, {displayValue: "综合", systemValue: "C"}]

2

enum GoalProgressMeasurements {
    Percentage = 1,
    Numeric_Target = 2,
    Completed_Tasks = 3,
    Average_Milestone_Progress = 4,
    Not_Measured = 5
}
    
const array = []
    
for (const [key, value] of Object.entries(GoalProgressMeasurements)) {
    if (!Number.isNaN(Number(key))) {
        continue;
    }

    array.push({ id: value, name: key.replace('_', '') });
}

console.log(array);


请在回答中始终放置上下文而不仅是粘贴代码。有关更多详细信息,请参见此处 - gehbiszumeis

2

有一个简单的解决方案,当你运行Object.keys(Enum)时,它会给你一个值和键的数组,在第一个切片中是值,在第二个切片中是键,那么为什么我们不只返回第二个切片呢?下面的代码对我有效。

enum Enum {
   ONE,
   TWO,
   THREE,
   FOUR,
   FIVE,
   SIX,
   SEVEN
}
const keys = Object.keys(Enum); 
console.log(keys.slice(keys.length / 2));

好奇这个为什么被踩了?我也有同样的想法。担心的是 TypeScript 会改变并不再以相同的方式制作枚举吗? - Tony Smith
1
Object.keys 的顺序不能保证。 - polkovnikov.ph

1

让枚举变量为:

 enum EnumName {
      A = 1,
      B = 2
    };

那么列表就是:

const list = Object.keys(Enum)
.filter((value => isNaN(Number(value)) === false))
      .map(key => ({ id: key, value: Enum[key] }));

列表的值将会是

list = [ 
{ id:1 , value: A },
{ id:2 , value: B },
];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接