Tengo una enumeración definida de esta manera:
export enum GoalProgressMeasurements {
Percentage = 1,
Numeric_Target = 2,
Completed_Tasks = 3,
Average_Milestone_Progress = 4,
Not_Measured = 5
}
Sin embargo, me gustaría que se representara como una matriz / lista de objetos de nuestra API como se muestra a continuación:
[{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'}]
¿Hay una forma fácil y nativa de hacer esto o tengo que construir una función que arroje la enumeración tanto a un int como a una cadena, y construya los objetos en una matriz?
javascript
arrays
typescript
enums
casting
AnimaSola
fuente
fuente
GoalProgressMeasurements[GoalProgressMeasurements.Completed_Tasks]
para obtener el nombre de enumeración. No sé si eso ayuda.Respuestas:
Un poco complicado es que TypeScript 'duplicará' la asignación de la enumeración en el objeto emitido, por lo que se puede acceder a él tanto por clave como por valor.
enum MyEnum { Part1 = 0, Part2 = 1 }
será emitido como
{ Part1: 0, Part2: 1, 0: 'Part1', 1: 'Part2' }
Por lo tanto, primero debe filtrar el objeto antes de realizar el mapeo. Entonces, la solución de @Diullei tiene la respuesta correcta. Aquí está mi implementación:
// 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]); }
Úselo así:
export enum GoalProgressMeasurements { Percentage, Numeric_Target, Completed_Tasks, Average_Milestone_Progress, Not_Measured } console.log(ToArray(GoalProgressMeasurements));
fuente
enum MyEnum { Part1 = 0, Part2 = 1 }
convierte en{ Part1: 0, Part2: 1, 0: 'Part1', 1: 'Part2' }
entonces, ¿por qué cuandoconsole.log(Object.values(MyEnum))
solo imprime 0,1?Object.values(MyEnum)
evalúa como["Part1", "Part2", 0, 1]
console.log(Object.values(MyEnum))
en mi componente. Estoy usando angular, no estoy seguro de si eso está relacionado. No tengo tanta experiencia en TypeScriptSi está utilizando ES6
Le dará una matriz de valores de la enumeración dada .
enum Colors { WHITE = 0, BLACK = 1, BLUE = 3 } const colorValueArray = Object.values(Colors); //[ 'WHITE', 'BLACK', 'BLUE', 0, 1, 3 ]
Te pondrás
colorValueArray
así[ 'WHITE', 'BLACK', 'BLUE', 0, 1, 3 ]
. Todas las claves estarán en la primera mitad de la matriz y todos los valores en la segunda mitad.fuente
(string | YourEnumType)[]
que no es el que podría desear en cada caso.Las enumeraciones son objetos reales que existen en tiempo de ejecución. Entonces puede revertir el mapeo haciendo algo como esto:
let value = GoalProgressMeasurements.Not_Measured; console.log(GoalProgressMeasurements[value]); // => Not_Measured
En base a eso, puede usar el siguiente código:
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);
Referencia: https://www.typescriptlang.org/docs/handbook/enums.html
fuente
= 2
hasta que= 5
- Cualquier valor posterior= 1
es +1 automáticamente.Solución fácil. Puede usar la siguiente función para convertir su Enum en una matriz de objetos.
buildGoalProgressMeasurementsArray(): Object[] { return Object.keys(GoalProgressMeasurements) .map(key => ({ id: GoalProgressMeasurements[key], name: key })) }
Si necesita eliminar ese subrayado, podríamos usar expresiones regulares de la siguiente manera:
buildGoalProgressMeasurementsArray(): Object[] { return Object.keys(GoalProgressMeasurements) .map(key => ({ id: GoalProgressMeasurements[key], name: key.replace(/_/g, ' ') })) }
fuente
Object.keys(GoalProgressMeasurements) .filter(key => typeof GoalProgressMeasurements[key] === 'number') .map(key => ({ id: GoalProgressMeasurements[key], name: key }))
yo suelo
Object.entries(GoalProgressMeasurement).filter(e => !isNaN(e[0]as any)).map(e => ({ name: e[1], id: e[0] }));
Una línea simple que hace el trabajo.
Hace el trabajo en 3 sencillos pasos
: carga la combinación de claves y valores usando
Object.entries
.- Filtra los no números (ya que el mecanografiado genera los valores para la búsqueda inversa).
- Luego lo asignamos al objeto de matriz que nos gusta.
fuente
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]); } }
fuente
Esto le dará una matriz de valores de enumeración:
Object.values(myEnum);
fuente
Primero obtenemos una matriz de claves para esta enumeración. Luego, usando la función map (), convertimos los datos al formato deseado. id se obtiene de la clave, nombre se obtiene de enum por la misma clave.
const converted = Object.keys(GoalProgressMeasurements).map(key => { return { id: GoalProgressMeasurements[key], name: key, }; });
fuente
No me gustó ninguna de las respuestas anteriores porque ninguna de ellas maneja correctamente la combinación de cadenas / números que pueden ser valores en las enumeraciones de TypeScript.
La siguiente función sigue la semántica de las enumeraciones de TypeScript para proporcionar un mapa adecuado de claves para los valores. A partir de ahí, obtener una matriz de objetos o solo las claves o solo los valores es trivial.
/** * 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; }
Ejemplo de uso:
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
También señalaré que el OP está pensando en enumeraciones al revés. La "clave" en la enumeración está técnicamente en el lado izquierdo y el valor está en el lado derecho. TypeScript le permite repetir los valores en el RHS tanto como desee.
fuente
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);
fuente
Puedes hacerlo de esta manera:
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"), }
Y puedes usarlo así:
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;
Puede ampliar GoalProgressMeasurement con propiedades adicionales del objeto según lo necesite. Estoy usando este enfoque para cada enumeración que debería ser un objeto que contenga más de un valor.
fuente
Dado que las enumeraciones con valores de cadenas difieren de las que tienen valores numéricos, es mejor filtrar los no números de la solución @ user8363.
Así es como puede obtener valores de enum, ya sea cadenas, números de mezcla:
//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]); }
fuente
Me sorprende que en un hilo de TypeScript nadie haya dado una función válida de TypeScript con soporte de escritura. Aquí está la variación de la solución @ 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] ); }
fuente
Hay una solución simple, así que cuando ejecute
Object.keys(Enum)
eso le dará una matriz de valores y claves, en los valores del primer segmento y en el segundo, las claves, entonces, ¿por qué no devolvemos el segundo segmento? Este código a continuación funciona para mí. .enum Enum { ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN } const keys = Object.keys(Enum); console.log(keys.slice(keys.length / 2));
fuente