Mam wyliczenie zdefiniowane w ten sposób:
export enum GoalProgressMeasurements {
Percentage = 1,
Numeric_Target = 2,
Completed_Tasks = 3,
Average_Milestone_Progress = 4,
Not_Measured = 5
}
Chciałbym jednak, aby był reprezentowany jako tablica / lista obiektów z naszego API, jak poniżej:
[{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'}]
Czy istnieje prosty i natywny sposób, aby to zrobić, czy też muszę zbudować funkcję, która rzutuje wyliczenie zarówno na int, jak i na ciąg, i zbudować obiekty w tablicy?
javascript
arrays
typescript
enums
casting
AnimaSola
źródło
źródło
GoalProgressMeasurements[GoalProgressMeasurements.Completed_Tasks]
aby uzyskać nazwę wyliczenia. Nie wiem, czy to pomaga.Odpowiedzi:
Trudnym problemem jest to, że TypeScript „podwaja” mapowanie wyliczenia w emitowanym obiekcie, dzięki czemu można uzyskać do niego dostęp zarówno za pomocą klucza, jak i wartości.
enum MyEnum { Part1 = 0, Part2 = 1 }
zostanie wyemitowany jako
{ Part1: 0, Part2: 1, 0: 'Part1', 1: 'Part2' }
Dlatego przed mapowaniem należy najpierw przefiltrować obiekt. Tak więc rozwiązanie @Diullei ma właściwą odpowiedź. Oto moja realizacja:
// 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]); }
Użyj tego w ten sposób:
export enum GoalProgressMeasurements { Percentage, Numeric_Target, Completed_Tasks, Average_Milestone_Progress, Not_Measured } console.log(ToArray(GoalProgressMeasurements));
źródło
enum MyEnum { Part1 = 0, Part2 = 1 }
zamienia się w{ Part1: 0, Part2: 1, 0: 'Part1', 1: 'Part2' }
to, dlaczego poconsole.log(Object.values(MyEnum))
prostu drukuje tylko 0,1?Object.values(MyEnum)
ocenia się na["Part1", "Part2", 0, 1]
console.log(Object.values(MyEnum))
w moim komponencie. Używam kątowej, nie jestem pewien, czy to jest powiązane. Nie mam takiego doświadczenia w TypeScriptJeśli używasz ES8
Tylko w tym przypadku będzie działać idealnie. To da ci tablicę wartości podanego wyliczenia .
enum Colors { WHITE = 0, BLACK = 1, BLUE = 3 } const colorValueArray = Object.values(Colors); //[ 'WHITE', 'BLACK', 'BLUE', 0, 1, 3 ]
Otrzymasz
colorValueArray
taki[ 'WHITE', 'BLACK', 'BLUE', 0, 1, 3 ]
. Wszystkie klucze będą znajdować się w pierwszej połowie tablicy, a wszystkie wartości w drugiej połowie.Nawet ten rodzaj wyliczenia będzie działał dobrze
Ale to rozwiązanie nie zadziała w przypadku heterogenicznych wyliczeń, takich jak to
enum BooleanLikeHeterogeneousEnum { No = 0, Yes = "YES", }
źródło
(string | YourEnumType)[]
który nie jest tym, czego możesz chcieć w każdym przypadku.Object.values()
nie jest częścią ES6. Jest częścią ES2017.Wyliczenia to rzeczywiste obiekty istniejące w czasie wykonywania. Możesz więc odwrócić mapowanie, wykonując coś takiego:
let value = GoalProgressMeasurements.Not_Measured; console.log(GoalProgressMeasurements[value]); // => Not_Measured
Na tej podstawie możesz użyć następującego kodu:
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);
Źródła: https://www.typescriptlang.org/docs/handbook/enums.html
źródło
= 2
dopóki= 5
- Cokolwiek później nie= 1
daje automatycznie +1.Łatwe rozwiązanie. Możesz użyć następującej funkcji, aby przekonwertować Enum na tablicę obiektów.
buildGoalProgressMeasurementsArray(): Object[] { return Object.keys(GoalProgressMeasurements) .map(key => ({ id: GoalProgressMeasurements[key], name: key })) }
Jeśli chcesz usunąć to podkreślenie, możemy użyć wyrażenia regularnego w następujący sposób:
buildGoalProgressMeasurementsArray(): Object[] { return Object.keys(GoalProgressMeasurements) .map(key => ({ id: GoalProgressMeasurements[key], name: key.replace(/_/g, ' ') })) }
źródło
Object.keys(GoalProgressMeasurements) .filter(key => typeof GoalProgressMeasurements[key] === 'number') .map(key => ({ id: GoalProgressMeasurements[key], name: key }))
używam
Object.entries(GoalProgressMeasurement).filter(e => !isNaN(e[0]as any)).map(e => ({ name: e[1], id: e[0] }));
Prosta 1 linia, która spełnia swoje zadanie.
Wykonuje zadanie w 3 prostych krokach
- ładuje kombinację kluczy i wartości za pomocą
Object.entries
.- Filtruje nieliczby (ponieważ maszynopis generuje wartości do wyszukiwania wstecznego).
- Następnie mapujemy go na obiekt tablicy, który nam się podoba.
źródło
Object.values(GoalProgressMeasurement)
To da ci tablicę wartości wyliczeniowych:
Object.values(myEnum);
źródło
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]); } }
źródło
Nie podobała mi się żadna z powyższych odpowiedzi, ponieważ żadna z nich nie obsługuje poprawnie mieszaniny ciągów / liczb, które mogą być wartościami w wyliczeniach TypeScript.
Poniższa funkcja jest zgodna z semantyką wyliczeń TypeScript, aby zapewnić odpowiednią Mapę kluczy do wartości. Stamtąd uzyskanie tablicy obiektów, samych kluczy lub samych wartości jest trywialne.
/** * 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; }
Przykładowe zastosowanie:
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
Zwrócę również uwagę, że OP myśli o wyliczeniach wstecz. „Klucz” w wyliczeniu jest technicznie po lewej stronie, a wartość po prawej stronie. TypeScript umożliwia powtarzanie wartości na RHS tyle, ile chcesz.
źródło
Najpierw otrzymujemy tablicę kluczy dla tego wyliczenia. Następnie za pomocą funkcji map () konwertujemy dane do żądanego formatu. id jest uzyskiwany z klucza, nazwa jest uzyskiwana z wyliczenia przez ten sam klucz.
const converted = Object.keys(GoalProgressMeasurements).map(key => { return { id: GoalProgressMeasurements[key], name: key, }; });
źródło
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);
źródło
Jest proste rozwiązanie, więc kiedy uruchomisz
Object.keys(Enum)
to, otrzymasz tablicę wartości i kluczy, w pierwszym wycinku wartości i w drugim kluczach, więc dlaczego nie zwrócimy po prostu drugiego wycinka, ten kod poniżej działa dla mnie .enum Enum { ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN } const keys = Object.keys(Enum); console.log(keys.slice(keys.length / 2));
źródło
Oto prosta funkcja z poprawnym pisaniem, której używam
/** * 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][]; }
Przykład użycia:
enum Colors { Red = 1, Blue = 2, } enumToArray(Colors)
źródło
Możesz to zrobić w ten sposób:
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"), }
Możesz go używać w ten sposób:
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;
W razie potrzeby możesz rozszerzyć GoalProgressMeasurement o dodatkowe właściwości obiektu. Używam tego podejścia do każdego wyliczenia, które powinno być obiektem zawierającym więcej niż wartość.
źródło
Ponieważ wyliczenia z wartościami ciągów różnią się od tych, które mają wartości liczbowe, lepiej jest filtrować wartości inne niż liczby z rozwiązania @ user8363.
Oto, w jaki sposób możesz uzyskać wartości z wyliczenia zarówno ciągów, jak i liczb mieszanych:
//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]); }
źródło
Jestem zaskoczony, że w wątku TypeScript nikt nie dał prawidłowej funkcji TypeScript z obsługą pisania. Oto odmiana rozwiązania @ 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] ); }
źródło
Nie sądzę, aby kolejność mogła być zagwarantowana, w przeciwnym razie łatwo byłoby wyciąć drugą połowę
Object.entries
wyniku i zmapować stamtąd.Jedyny (bardzo drobny) problem z powyższymi odpowiedziami jest taki
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 }
źródło
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]); }
źródło