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

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和字符串,并将对象构建为数组?


当前回答

我从几个月前就了解了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: "Basic", systemValue: "B"}, {displayValue: "Consolidated", systemValue: "C"}]

其他回答

TS:

仅适用于短(<10个元素)enum

const keys = Object.keys(Enum).filter((el: string) => el.length > 1)
console.log(keys)

Object.keys()将返回一个包含['0','1','2','enumElement1', 'enumElement2', enumElement3']的数组 Filter()获取每个元素并检查其长度(因为字符串),并从结果数组中排除所有数字

我不认为顺序是可以保证的,否则就很容易切片Object的后半部分。条目的结果和映射来自那里。

上述答案的唯一(非常小的)问题是

字符串和数字之间有很多不必要的类型转换。 当一次迭代同样干净有效时,条目将迭代两次。

type StandardEnum = { [id: string]: number | string; [nu: number]: string;}

function enumToList<T extends StandardEnum> (enm: T) : { id: number; description: string }[] {
    return Object.entries(enm).reduce((accum, kv) => {
        if (typeof kv[1] === 'number') {
            accum.push({ id: kv[1], description: kv[0] })
        }
        return accum
    }, []) // if enum is huge, perhaps pre-allocate with new Array(entries.length / 2), however then push won't work, so tracking an index would also be required
}

我不喜欢上面的答案,因为它们都不能正确地处理字符串/数字的混合,可以在TypeScript enum中作为值。

下面的函数遵循TypeScript枚举的语义,给出键到值的正确映射。从那里,获取一个对象数组或者仅仅是键或者仅仅是值是很简单的。

/**
 * Converts the given enum to a map of the keys to the values.
 * @param enumeration The enum to convert to a map.
 */
function enumToMap(enumeration: any): Map<string, string | number> {
  const map = new Map<string, string | number>();
  for (let key in enumeration) {
      //TypeScript does not allow enum keys to be numeric
      if (!isNaN(Number(key))) continue;

      const val = enumeration[key] as string | number;

      //TypeScript does not allow enum value to be null or undefined
      if (val !== undefined && val !== null)
          map.set(key, val);
  }

  return map;
}

使用示例:

enum Dog {
    Rover = 1,
    Lassie = "Collie",
    Fido = 3,
    Cody = "Mutt",
}

let map = enumToMap(Dog); //Map of keys to values

let objs = Array.from(map.entries()).map(m => ({id: m[1], name: m[0]})); //Objects as asked for in OP
let entries = Array.from(map.entries()); //Array of each entry
let keys = Array.from(map.keys()); //An array of keys
let values = Array.from(map.values()); //An array of values

我还要指出OP是逆向思考枚举的。枚举中的“键”在技术上是在左边,而值在右边。TypeScript允许你尽可能多地重复RHS上的值。

一个棘手的地方是TypeScript会在触发对象中'double'映射enum,所以它可以通过键和值访问。

enum MyEnum {
    Part1 = 0,
    Part2 = 1
}

将以

{
   Part1: 0,
   Part2: 1,
   0: 'Part1',
   1: 'Part2'
}

所以你应该在映射之前先过滤对象。所以@Diullei的解决方案是正确的。这是我的实现:

// Helper
const StringIsNumber = value => isNaN(Number(value)) === false;

// Turn enum into array
function ToArray(enumme) {
    return Object.keys(enumme)
        .filter(StringIsNumber)
        .map(key => enumme[key]);
}

像这样使用它:

export enum GoalProgressMeasurements {
    Percentage,
    Numeric_Target,
    Completed_Tasks,
    Average_Milestone_Progress,
    Not_Measured
}

console.log(ToArray(GoalProgressMeasurements));

这将返回一个枚举值数组:

 Object.values(myEnum);