TypeScript枚举到对象数组

时间:2017-03-29 17:53:31

标签: javascript arrays typescript enums casting

我有这样定义的枚举:

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和string的函数,并将对象构建为数组?

19 个答案:

答案 0 :(得分:17)

枚举是运行时存在的真实对象。所以你可以反转映射做这样的事情:

let value = GoalProgressMeasurements.Not_Measured;
console.log(GoalProgressMeasurements[value]);
// => Not_Measured

基于此,您可以使用以下代码:

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);

参考:https://www.typescriptlang.org/docs/handbook/enums.html

答案 1 :(得分:13)

如果您使用的是ES6

它将为您提供给定枚举的值数组。

enum colors = {
  "WHITE" : 0,
  "BLACK" : 1
}

const colorValueArray = Object.values(colors);

答案 2 :(得分:12)

一个棘手的问题是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]);
}

像这样使用它:

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

console.log(ToArray(GoalProgressMeasurements));

答案 3 :(得分:12)

我用

Object.entries(GoalProgressMeasurement).filter(e => !isNaN(e[0]as any)).map(e => ({ name: e[1], id: e[0] }));

完成任务的简单1行。

只需3个简单步骤即可完成工作
-使用Object.entries加载键和值的组合。
-过滤掉非数字(因为打字稿会生成用于反向查找的值)。
-然后将其映射到所需的数组对象。

答案 4 :(得分:9)

这将为您提供一系列枚举值:

Value

答案 5 :(得分:8)

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

 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, ' ') }))
 }

答案 6 :(得分:4)

首先,我们获得此枚举的键数组。然后,使用map()函数,将数据转换为所需的格式。 id是从键获得的,name是通过相同键从枚举获得的。

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

答案 7 :(得分:2)

我不喜欢上述任何答案,因为它们都不能正确处理可能是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;
}

示例用法:

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

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

lets 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上重复很多值。

答案 8 :(得分:1)

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]);
    }
}

答案 9 :(得分:1)

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

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

答案 10 :(得分:1)

TS:

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

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

答案 11 :(得分:0)

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);

答案 12 :(得分:0)

您可以通过以下方式做到这一点:

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"),
}

您可以像这样使用它:

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。我对每个枚举都应该使用这种方法,该枚举应该是一个包含更多值的对象。

答案 13 :(得分:0)

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

这是从字符串或混合数中获取枚举值的方法:

    //Helper
    export const StringIsNotNumber = value => isNaN(Number(value)) === true;
    
    // Turn enum into array
    export function enumToArray(enumme) {
      return Object.keys(enumme)
       .filter(StringIsNotNumber)
       .map(key => enumme[key]);
    }

答案 14 :(得分:0)

我对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]
  );
}

答案 15 :(得分:0)

我认为不能保证顺序,否则将Object.entries结果的后一半切成薄片并从那里映射就足够容易了。

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

  • 字符串和数字之间有很多不必要的类型转换。
  • 当一次迭代同样干净有效时,条目将被重复两次。
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
}

答案 16 :(得分:0)

这是我使用正确键入的简单功能

/**
 * Helper to produce an array of enum values.
 * @param enumeration Enumeration object.
 */
export function enumToArray<T, G extends keyof T = keyof T>(enumeration: T): T[G][] {
  // tslint:disable: comment-format

  // enum Colors {
  //   WHITE = 0,
  //   BLACK = 1,
  // }
  // Object.values(Colors) will produce ['WHITE', 'BLACK', 0, 1]

  // So, simply slice the second half
  const enumValues = Object.values(enumeration);
  return enumValues.slice(enumValues.length / 2, enumValues.length) as T[G][];
}

用法示例:

enum Colors {
  Red = 1,
  Blue = 2,
}
enumToArray(Colors)

答案 17 :(得分:0)

function enumKeys(_enum) {
  const entries = Object.entries(_enum).filter(e => !isNaN(Number(e[0])));
  if (!entries.length) {
    // enum has string values so we can use Object.keys
    return Object.keys(_enum);
  }
  return entries.map(e => e[1]);
}

答案 18 :(得分:0)

另一种使用 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' } 
] 

无耻地从这个blog中偷走