Eu tenho um enum definido desta forma:
export enum GoalProgressMeasurements {
Percentage = 1,
Numeric_Target = 2,
Completed_Tasks = 3,
Average_Milestone_Progress = 4,
Not_Measured = 5
}
No entanto, gostaria que fosse representado como um array / lista de objetos de nossa API como a seguir:
[{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'}]
Existe uma maneira fácil e nativa de fazer isso ou eu tenho que construir uma função que converta o enum para um int e uma string e construir os objetos em uma matriz?
javascript
arrays
typescript
enums
casting
AnimaSola
fonte
fonte
GoalProgressMeasurements[GoalProgressMeasurements.Completed_Tasks]
obter o nome do enum. Não sei se isso ajuda.Respostas:
Uma parte complicada é que o TypeScript fará o mapeamento 'duplo' do enum no objeto emitido, para que ele possa ser acessado por chave e valor.
enum MyEnum { Part1 = 0, Part2 = 1 }
será emitido como
{ Part1: 0, Part2: 1, 0: 'Part1', 1: 'Part2' }
Portanto, você deve filtrar o objeto antes de mapear. Portanto, a solução de @Diullei tem a resposta certa. Aqui está minha implementação:
// 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]); }
Use-o assim:
export enum GoalProgressMeasurements { Percentage, Numeric_Target, Completed_Tasks, Average_Milestone_Progress, Not_Measured } console.log(ToArray(GoalProgressMeasurements));
fonte
enum MyEnum { Part1 = 0, Part2 = 1 }
transforma em{ Part1: 0, Part2: 1, 0: 'Part1', 1: 'Part2' }
então, por que quando vocêconsole.log(Object.values(MyEnum))
imprime apenas 0,1?Object.values(MyEnum)
avalia para["Part1", "Part2", 0, 1]
console.log(Object.values(MyEnum))
no meu componente. Estou usando angular, não tenho certeza se está relacionado. Não tenho tanta experiência em TypeScriptSe você estiver usando ES8
Apenas neste caso funcionará perfeitamente bem. Ele lhe dará a matriz de valor do enum fornecido .
enum Colors { WHITE = 0, BLACK = 1, BLUE = 3 } const colorValueArray = Object.values(Colors); //[ 'WHITE', 'BLACK', 'BLUE', 0, 1, 3 ]
Você vai ficar
colorValueArray
assim[ 'WHITE', 'BLACK', 'BLUE', 0, 1, 3 ]
. Todas as chaves estarão na primeira metade da matriz e todos os valores na segunda metade.Mesmo este tipo de enum funcionará bem
Mas esta solução não funcionará para enums heterogêneos como este
enum BooleanLikeHeterogeneousEnum { No = 0, Yes = "YES", }
fonte
(string | YourEnumType)[]
que não é o que você deseja em cada caso.Object.values()
não faz parte do ES6. Faz parte do ES2017.Enums são objetos reais que existem em tempo de execução. Portanto, você pode reverter o mapeamento fazendo algo assim:
let value = GoalProgressMeasurements.Not_Measured; console.log(GoalProgressMeasurements[value]); // => Not_Measured
Com base nisso, você pode usar o seguinte 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);
Referência: https://www.typescriptlang.org/docs/handbook/enums.html
fonte
= 2
até= 5
- Qualquer coisa depois= 1
é +1 automaticamente.Solução fácil. Você pode usar a seguinte função para converter seu Enum em uma matriz de objetos.
buildGoalProgressMeasurementsArray(): Object[] { return Object.keys(GoalProgressMeasurements) .map(key => ({ id: GoalProgressMeasurements[key], name: key })) }
Se você precisasse remover esse sublinhado, poderíamos usar regex da seguinte maneira:
buildGoalProgressMeasurementsArray(): Object[] { return Object.keys(GoalProgressMeasurements) .map(key => ({ id: GoalProgressMeasurements[key], name: key.replace(/_/g, ' ') })) }
fonte
Object.keys(GoalProgressMeasurements) .filter(key => typeof GoalProgressMeasurements[key] === 'number') .map(key => ({ id: GoalProgressMeasurements[key], name: key }))
eu uso
Object.entries(GoalProgressMeasurement).filter(e => !isNaN(e[0]as any)).map(e => ({ name: e[1], id: e[0] }));
Uma linha simples que faz o trabalho.
Ele faz o trabalho em 3 etapas simples
- Carrega a combinação de chaves e valores usando
Object.entries
.- Filtra os não números (uma vez que o texto digitado gera os valores para pesquisa reversa).
- Em seguida, mapeamos para o objeto de matriz que gostamos.
fonte
Object.values(GoalProgressMeasurement)
Isso lhe dará uma matriz de valores enum:
Object.values(myEnum);
fonte
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]); } }
fonte
Primeiro, obtemos uma matriz de chaves para este enum. Então, usando a função map (), convertemos os dados para o formato desejado. id é obtido a partir da chave, o nome é obtido a partir de enum pela mesma chave.
const converted = Object.keys(GoalProgressMeasurements).map(key => { return { id: GoalProgressMeasurements[key], name: key, }; });
fonte
Não gostei de nenhuma das respostas acima porque nenhuma delas trata corretamente a mistura de strings / números que podem ser valores em enums do TypeScript.
A função a seguir segue a semântica dos enums do TypeScript para fornecer um mapa adequado de chaves para valores. A partir daí, obter uma matriz de objetos ou apenas as chaves ou apenas os valores é 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; }
Exemplo 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
Também destacarei que o OP está pensando em enums ao contrário. A "chave" no enum está tecnicamente no lado esquerdo e o valor está no lado direito. O TypeScript permite que você repita os valores no RHS tanto quanto desejar.
fonte
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);
fonte
Existe uma solução simples, então quando você executar
Object.keys(Enum)
isso vai lhe dar uma matriz de valores e chaves, nos valores da primeira fatia e na segunda chave, então por que não retornamos apenas a segunda fatia, este código abaixo funciona para mim .enum Enum { ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN } const keys = Object.keys(Enum); console.log(keys.slice(keys.length / 2));
fonte
Aqui está a função simples com a digitação correta que eu uso
/** * 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][]; }
Exemplo de uso:
enum Colors { Red = 1, Blue = 2, } enumToArray(Colors)
fonte
Você pode fazer isso desta forma:
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"), }
E você pode usá-lo assim:
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;
Você pode estender o GoalProgressMeasurement com propriedades adicionais do objeto conforme necessário. Estou usando essa abordagem para cada enumeração que deve ser um objeto contendo mais do que um valor.
fonte
Uma vez que enums com valores de Strings diferem daqueles que têm valores de número, é melhor filtrar os não-números da solução @ user8363.
Aqui está como você pode obter valores de enum de strings, números de mistos:
//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]); }
fonte
Estou surpreso em um thread de TypeScript que ninguém forneceu uma função TypeScript válida com suporte para digitação. Aqui está uma variação da solução @ 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] ); }
fonte
Eu não acho que a ordem pode ser garantida, caso contrário, seria fácil cortar a segunda metade do
Object.entries
resultado e mapear a partir daí.O único (muito pequeno) problema com as respostas acima é que
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 }
fonte
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]); }
fonte