Javascript TypeScript枚举到对象数组

Javascript TypeScript枚举到对象数组,javascript,arrays,typescript,enums,casting,Javascript,Arrays,Typescript,Enums,Casting,我有这样定义的枚举: export enum GoalProgressMeasurements { Percentage = 1, Numeric_Target = 2, Completed_Tasks = 3, Average_Milestone_Progress = 4, Not_Measured = 5 } export enum GoalProgressMeasurements { Percentage = 1, Numeric_

我有这样定义的枚举:

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

export class GoalProgressMeasurement {
    constructor(public goalProgressMeasurement: GoalProgressMeasurements, public name: string) {
    }
}

export var goalProgressMeasurements: { [key: number]: GoalProgressMeasurement } = {
    1: new GoalProgressMeasurement(GoalProgressMeasurements.Percentage, "Percentage"),
    2: new GoalProgressMeasurement(GoalProgressMeasurements.Numeric_Target, "Numeric Target"),
    3: new GoalProgressMeasurement(GoalProgressMeasurements.Completed_Tasks, "Completed Tasks"),
    4: new GoalProgressMeasurement(GoalProgressMeasurements.Average_Milestone_Progress, "Average Milestone Progress"),
    5: new GoalProgressMeasurement(GoalProgressMeasurements.Not_Measured, "Not Measured"),
}
但是,我希望将其表示为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和字符串的函数,并将对象构建到数组中?

枚举是运行时存在的真实对象。因此,您可以通过以下方式反转映射:

let value = GoalProgressMeasurements.Not_Measured;
console.log(GoalProgressMeasurements[value]);
// => Not_Measured
export enum GoalProgressMeasurements {
    Percentage,
    Numeric_Target,
    Completed_Tasks,
    Average_Milestone_Progress,
    Not_Measured
}

console.log(ToArray(GoalProgressMeasurements));
var gpm: GoalProgressMeasurement = goalProgressMeasurements[GoalProgressMeasurements.Percentage];
var gpmName: string = gpm.name;

var myProgressId: number = 1; // the value can come out of drop down selected value or from back-end , so you can imagine the way of using
var gpm2: GoalProgressMeasurement = goalProgressMeasurements[myProgressId];
var gpmName: string = gpm.name;
基于此,您可以使用以下代码:

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

let map: {id: number; name: string}[] = [];

for(var n in GoalProgressMeasurements) {
    if (typeof GoalProgressMeasurements[n] === 'number') {
        map.push({id: <any>GoalProgressMeasurements[n], name: n});
    }
}

console.log(map);
导出枚举GoalProgressMeasurements{
百分比=1,
数值_目标=2,
已完成的任务=3,
平均里程碑进度=4,
未测量=5
}
let映射:{id:number;name:string}[]=[];
for(目标程序测量中的var n){
if(目标程序测量的类型[n]=“编号”){

push({id:

简易解决方案。您可以使用以下函数将枚举转换为对象数组

 buildGoalProgressMeasurementsArray(): Object[] {

    return Object.keys(GoalProgressMeasurements)
              .map(key => ({ id: GoalProgressMeasurements[key], name: key }))
 }
如果您需要去掉下划线,我们可以按如下方式使用正则表达式:

buildGoalProgressMeasurementsArray(): Object[] {

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

一个棘手的问题是,TypeScript将“双重”映射发出对象中的枚举,因此可以通过键和值访问它

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]);
}
像这样使用它:

let value = GoalProgressMeasurements.Not_Measured;
console.log(GoalProgressMeasurements[value]);
// => Not_Measured
export enum GoalProgressMeasurements {
    Percentage,
    Numeric_Target,
    Completed_Tasks,
    Average_Milestone_Progress,
    Not_Measured
}

console.log(ToArray(GoalProgressMeasurements));
var gpm: GoalProgressMeasurement = goalProgressMeasurements[GoalProgressMeasurements.Percentage];
var gpmName: string = gpm.name;

var myProgressId: number = 1; // the value can come out of drop down selected value or from back-end , so you can imagine the way of using
var gpm2: GoalProgressMeasurement = goalProgressMeasurements[myProgressId];
var gpmName: string = gpm.name;

您可以这样做:

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

export class GoalProgressMeasurement {
    constructor(public goalProgressMeasurement: GoalProgressMeasurements, public name: string) {
    }
}

export var goalProgressMeasurements: { [key: number]: GoalProgressMeasurement } = {
    1: new GoalProgressMeasurement(GoalProgressMeasurements.Percentage, "Percentage"),
    2: new GoalProgressMeasurement(GoalProgressMeasurements.Numeric_Target, "Numeric Target"),
    3: new GoalProgressMeasurement(GoalProgressMeasurements.Completed_Tasks, "Completed Tasks"),
    4: new GoalProgressMeasurement(GoalProgressMeasurements.Average_Milestone_Progress, "Average Milestone Progress"),
    5: new GoalProgressMeasurement(GoalProgressMeasurements.Not_Measured, "Not Measured"),
}
您可以这样使用它:

let value = GoalProgressMeasurements.Not_Measured;
console.log(GoalProgressMeasurements[value]);
// => Not_Measured
export enum GoalProgressMeasurements {
    Percentage,
    Numeric_Target,
    Completed_Tasks,
    Average_Milestone_Progress,
    Not_Measured
}

console.log(ToArray(GoalProgressMeasurements));
var gpm: GoalProgressMeasurement = goalProgressMeasurements[GoalProgressMeasurements.Percentage];
var gpmName: string = gpm.name;

var myProgressId: number = 1; // the value can come out of drop down selected value or from back-end , so you can imagine the way of using
var gpm2: GoalProgressMeasurement = goalProgressMeasurements[myProgressId];
var gpmName: string = gpm.name;
您可以根据需要使用对象的其他属性来扩展GoalProgressMeasurement。对于每个应该是包含多于一个值的对象的枚举,我都使用这种方法。

类枚举帮助程序{
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]);
    }
}
静态getNamesAndValues(e:any){ 返回EnumHelpers.getNames(e).map(n=>({name:n,value:e[n]as T})); } 静态getNames(e:any){ 将EnumHelpers.getObjValues(e).filter(v=>typeof v==='string')作为字符串[]返回; } 静态GetValue(e:any){ 将EnumHelpers.getObjValues(e).filter(v=>typeof v==='number')作为T[]返回; } 静态getSelectList(e:any,stringConverter:(arg:U)=>string){ const selectList=newmap(); this.getValues(e).forEach(val=>selectList.set(val为T,stringConverter(val为未知的U)); 返回选择列表; } 静态getSelectListAsArray(e:any,stringConverter:(arg:U)=>string){ 返回Array.from(this.getSelectList(e,stringConverter),value=>({value:value[0]as T,presentation:value[1]}); } 私有静态getobjvalue(e:any):(数字|字符串)[]{ 返回Object.keys(e.map)(k=>e[k]); } }
如果您使用的是ES8

只有在这种情况下,它才能非常好地工作。它将为您提供给定枚举的值数组

您将得到如下
colorValueArray
['WHITE','BLACK','BLUE',0,1,3]
。所有键将位于数组的前半部分,所有值将位于后半部分

即使是这种枚举也可以正常工作

enum Operation {
    READ,
    WRITE,
    EXECUTE
}
但此解决方案不适用于异构枚举

enum BooleanLikeHeterogeneousEnum {
  No = 0,
  Yes = "YES",
}
enum GoalProgressMeasurements{
百分比=1,
数值_目标=2,
已完成的任务=3,
平均里程碑进度=4,
未测量=5
}
常量数组=[]
for(对象项的常量[键,值](goalProgressMeasures)){
如果(!Number.isNaN(编号(键))){
继续;
}
array.push({id:value,name:key.replace(“”,“”)});
}

console.log(array);
我不喜欢上面的任何答案,因为它们都不能正确处理TypeScript枚举中可能是值的字符串/数字的混合

下面的函数遵循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;
}

我还将指出,OP正在向后考虑枚举。从技术上讲,枚举中的“键”位于左侧,值位于右侧。TypeScript允许您在RHS上重复任意多的值。

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

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

一个简单的1行来完成这项工作

它通过3个简单的步骤完成这项工作
-使用
对象加载键和值的组合。条目

-过滤掉非数字(因为typescript生成反向查找的值)。

-然后将其映射到我们喜欢的数组对象。

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

 Object.values(myEnum);

由于具有字符串值的枚举与具有数字值的枚举不同,因此最好从@user8363解决方案中筛选非数字

以下是如何从enum字符串或混合数中获取值:

//助手
export const StringIsNotNumber=value=>isNaN(Number(value))==true;
//将枚举转换为数组
导出函数enumToArray(enumme){
返回Object.keys(enumme)
.filter(StringIsNotNumber)
.map(key=>enumme[key]);

}
我很惊讶TypeScript线程没有人提供有效的支持键入的TypeScript函数。下面是@user8363解决方案的变体:

const isStringNumber = (value: string) => isNaN(Number(value)) === false;

function enumToArray<T extends {}>(givenEnum: T) {
  return (Object.keys(givenEnum).filter(isStringNumber) as (keyof T)[]).map(
    (key) => givenEnum[key]
  );
}
const isStringNumber=(值:string)=>isNaN(数(值))==false;
函数枚举数组(给定值:T){
返回(Object.keys(givenEnum).filter(isStringNumber)为(keyof T)[]).map(
(键)=>givenEnum[键]
);
}

有一个简单的解决方案,所以当您运行
Object.keys(Enum)
时,它将在第一个片值和第二个片键中为您提供一个值和键的数组,所以为什么我们不返回第二个片,下面的代码对我很有用

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

我认为不能保证顺序,否则将
Object.entries的后半部分切片就足够容易了