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

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


当前回答

class EnumHelpers {

    static getNamesAndValues<T extends number>(e: any) {
        return EnumHelpers.getNames(e).map(n => ({ name: n, value: e[n] as T }));
    }

    static getNames(e: any) {
        return EnumHelpers.getObjValues(e).filter(v => typeof v === 'string') as string[];
    }

    static getValues<T extends number>(e: any) {
        return EnumHelpers.getObjValues(e).filter(v => typeof v === 'number') as T[];
    }

    static getSelectList<T extends number, U>(e: any, stringConverter: (arg: U) => string) {
        const selectList = new Map<T, string>();
        this.getValues(e).forEach(val => selectList.set(val as T, stringConverter(val as unknown as U)));
        return selectList;
    }

    static getSelectListAsArray<T extends number, U>(e: any, stringConverter: (arg: U) => string) {
        return Array.from(this.getSelectList(e, stringConverter), value => ({ value: value[0] as T, presentation: value[1] }));
    }

    private static getObjValues(e: any): (number | string)[] {
        return Object.keys(e).map(k => e[k]);
    }
}

其他回答

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

 Object.values(myEnum);

一个棘手的地方是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));

该方法基于语句: enum的键不能是数字

export const isNumeric = (num?: Value | null): num is number => {
  if (num === undefined || num === null) {
    return false;
  } 
  
  const number = +num;

  if (number - number !== 0) {
    // Discard Infinity and NaN
    return false;
  }

  if (number === num) {
    return true;
  }

  if (typeof num === 'string') {
    return !(number === 0 && num.trim() === '');
  }
  return false;
};

enum En  {
  ewq1 = 1,
  we2 = 'ss',
  sad = 'sad',
}

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

export const getEnumValues = <T extends TEnum>(enumerable: T) =>
  Object.keys(enumerable)
    .filter((x) => !isNumeric(x))
    .map((key) => enumerable[key] as T[keyof T]) 

console.log(getEnumValues(En)) // [1, "ss", "sad"] 

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()获取每个元素并检查其长度(因为字符串),并从结果数组中排除所有数字

简单的解决方案。您可以使用以下函数将Enum转换为对象数组。

 buildGoalProgressMeasurementsArray(): Object[] {

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

如果你需要去掉下划线,我们可以像下面这样使用regex:

buildGoalProgressMeasurementsArray(): Object[] {

    return Object.keys(GoalProgressMeasurements)
              .map(key => ({ id: GoalProgressMeasurements[key], name: key.replace(/_/g, ' ') }))
 }