Me gustaría iterar un TypeScript un enum
tipo y obtener cada nombre de símbolo enumerado, por ejemplo:
enum myEnum { entry1, entry2 }
for (var entry in myEnum) {
// use entry's name here, e.g., "entry1"
}
Me gustaría iterar un TypeScript un enum
tipo y obtener cada nombre de símbolo enumerado, por ejemplo:
enum myEnum { entry1, entry2 }
for (var entry in myEnum) {
// use entry's name here, e.g., "entry1"
}
Respuestas:
El código que publicaste funcionará; imprimirá todos los miembros de la enumeración, incluidos los valores de los miembros de la enumeración. Por ejemplo, el siguiente código:
enum myEnum { bar, foo }
for (var enumMember in myEnum) {
console.log("enum member: ", enumMember);
}
Imprimirá lo siguiente:
Enum member: 0
Enum member: 1
Enum member: bar
Enum member: foo
Si, en cambio, solo desea los nombres de los miembros y no los valores, puede hacer algo como esto:
for (var enumMember in myEnum) {
var isValueProperty = parseInt(enumMember, 10) >= 0
if (isValueProperty) {
console.log("enum member: ", myEnum[enumMember]);
}
}
Eso imprimirá solo los nombres:
Miembro de Enum: bar
Miembro de Enum: foo
Advertencia: esto se basa ligeramente en un detalle de implementación: TypeScript compila enumeraciones a un objeto JS con los valores de enumeración como miembros del objeto. Si TS decidiera implementarlos de manera diferente en el futuro, la técnica anterior podría romperse.
+enumMember >= 0
debería deberse a isFinite(+enumMember)
que los valores negativos o de coma flotante también se asignan inversamente. (
Aunque la respuesta ya está provista, casi nadie señaló el documentos
Aquí hay un fragmento
enum Enum {
A
}
let nameOfA = Enum[Enum.A]; // "A"
Tenga en cuenta que los miembros de cadena de enumeración no obtienen una asignación inversa generada en absoluto.
0
o 1
de esta enumeración? export enum Octave { ZERO = 0, ONE = 1 }
enum Enum {"A"}; let nameOfA = Enum[Enum.A];
? A partir de typescript@2.9.2 funciona bien para mí ...
Suponiendo que se apega a las reglas y solo produce enumeraciones con valores numéricos, puede usar este código. Esto maneja correctamente el caso en el que tiene un nombre que coincidentemente es un número válido
enum Color {
Red,
Green,
Blue,
"10" // wat
}
var names: string[] = [];
for(var n in Color) {
if(typeof Color[n] === 'number') names.push(n);
}
console.log(names); // ['Red', 'Green', 'Blue', '10']
Para mí, una forma más fácil, práctica y directa de entender lo que está sucediendo es la siguiente enumeración:
enum colors { red, green, blue };
Se convertirá esencialmente a esto:
var colors = { red: 0, green: 1, blue: 2,
[0]: "red", [1]: "green", [2]: "blue" }
Debido a esto, lo siguiente será cierto:
colors.red === 0
colors[colors.red] === "red"
colors["red"] === 0
Esto crea una manera fácil de obtener el nombre de un enumerado de la siguiente manera:
var color: colors = colors.red;
console.log("The color selected is " + colors[color]);
También crea una buena manera de convertir una cadena en un valor enumerado.
var colorName: string = "green";
var color: colors = colors.red;
if (colorName in colors) color = colors[colorName];
Las dos situaciones anteriores son una situación mucho más común, porque generalmente está mucho más interesado en el nombre de un valor específico y en la serialización de valores de forma genérica.
Si solo busca los nombres e itera más tarde, use:
Object.keys(myEnum).map(key => myEnum[key]).filter(value => typeof value === 'string') as string[];
Object.values(myEnum).filter(value => typeof value === 'string') as string[];
Object.values(myEnum).filter(value => typeof value === 'string').map(key => { return {id: myEnum[key], type: key }; });
Con la versión actual de TypeScript 1.8.9 utilizo enumeraciones escritas:
export enum Option {
OPTION1 = <any>'this is option 1',
OPTION2 = <any>'this is option 2'
}
con resultados en este objeto Javascript:
Option = {
"OPTION1": "this is option 1",
"OPTION2": "this is option 2",
"this is option 1": "OPTION1",
"this is option 2": "OPTION2"
}
así que tengo que consultar a través de claves y valores y solo devolver valores:
let optionNames: Array<any> = [];
for (let enumValue in Option) {
let optionNameLength = optionNames.length;
if (optionNameLength === 0) {
this.optionNames.push([enumValue, Option[enumValue]]);
} else {
if (this.optionNames[optionNameLength - 1][1] !== enumValue) {
this.optionNames.push([enumValue, Option[enumValue]]);
}
}
}
Y recibo las teclas de opción en una matriz:
optionNames = [ "OPTION1", "OPTION2" ];
A partir de TypeScript 2.4, las enumeraciones pueden contener inicializadores de cadenas https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html
Esto te permite escribir:
enum Order {
ONE = "First",
TWO = "Second"
}
console.log(`One is ${Order.ONE.toString()}`);
y obtener esta salida:
Uno es primero
Otra solución interesante que se encuentra aquí es usar ES6 Map:
export enum Type {
low,
mid,
high
}
export const TypeLabel = new Map<number, string>([
[Type.low, 'Low Season'],
[Type.mid, 'Mid Season'],
[Type.high, 'High Season']
]);
UTILIZAR
console.log(TypeLabel.get(Type.low)); // Low Season
Deje que ts-enum-util
( github , npm ) haga el trabajo por usted y proporcione muchas utilidades adicionales de tipo seguro. Funciona con cadenas y enumeraciones numéricas, ignorando adecuadamente las entradas de búsqueda inversa de índice numérico para enumeraciones numéricas:
Enum de cadena:
import {$enum} from "ts-enum-util";
enum Option {
OPTION1 = 'this is option 1',
OPTION2 = 'this is option 2'
}
// type: ("OPTION1" | "OPTION2")[]
// value: ["OPTION1", "OPTION2"]
const keys= $enum(Option).getKeys();
// type: Option[]
// value: ["this is option 1", "this is option 2"]
const values = $enum(Option).getValues();
Enumeración numérica:
enum Option {
OPTION1,
OPTION2
}
// type: ("OPTION1" | "OPTION2")[]
// value: ["OPTION1", "OPTION2"]
const keys= $enum(Option).getKeys();
// type: Option[]
// value: [0, 1]
const values = $enum(Option).getValues();
A partir de TypeScript 2.4, la enumeración ya no contendría la clave como miembro. fuente del archivo Léame de TypeScript
La advertencia es que las enumeraciones inicializadas en cadena no se pueden asignar de forma inversa para obtener el nombre del miembro de enumeración original. En otras palabras, no puede escribir Colors ["RED"] para obtener la cadena "Red".
Mi solución:
export const getColourKey = (value: string ) => {
let colourKey = '';
for (const key in ColourEnum) {
if (value === ColourEnum[key]) {
colourKey = key;
break;
}
}
return colourKey;
};
Puedes usar el enum-values
paquete que escribí cuando tuve el mismo problema:
var names = EnumValues.getNames(myEnum);
Basado en algunas respuestas anteriores, se me ocurrió esta firma de función de tipo seguro:
export function getStringValuesFromEnum<T>(myEnum: T): keyof T {
return Object.keys(myEnum).filter(k => typeof (myEnum as any)[k] === 'number') as any;
}
Uso:
enum myEnum { entry1, entry2 };
const stringVals = getStringValuesFromEnum(myEnum);
el tipo de stringVals
es'entry1' | 'entry2'
(keyof T)[]
lugar de keyof T
. Además, export
evita que su patio de recreo funcione.
Parece que ninguna de las respuestas aquí funcionará con enums de cadena en strict
modo.
Considere enum como:
enum AnimalEnum {
dog = "dog", cat = "cat", mouse = "mouse"
}
Acceder a esto con AnimalEnum["dog"]
puede provocar un error como:
Element implicitly has an 'any' type because expression of type 'any' can't be used to index type 'typeof AnimalEnum'.ts(7053)
.
Solución adecuada para ese caso, escríbala como:
AnimalEnum["dog" as keyof typeof AnimalEnum]
keyof
con typeof
! Otra solución parece bastante opaca, pero después de todo, creo que Typecript debe seguir mejorando en DX - Developer Experience for Enum
De acuerdo con la documentación de TypeScript, podemos hacer esto a través de Enum con funciones estáticas.
Obtenga Enum Name con funciones estáticas
enum myEnum {
entry1,
entry2
}
namespace myEnum {
export function GetmyEnumName(m: myEnum) {
return myEnum[m];
}
}
now we can call it like below
myEnum.GetmyEnumName(myEnum.entry1);
// result entry1
Para leer más sobre Enum con función estática, siga el siguiente enlace https://basarat.gitbooks.io/typescript/docs/enums.html
La única solución que funciona para mí en todos los casos (incluso si los valores son cadenas) es la siguiente:
var enumToString = function(enumType, enumValue) {
for (var enumMember in enumType) {
if (enumType[enumMember]==enumValue) return enumMember
}
}
Antigua pregunta, pero, ¿por qué no usar un const
mapa de objetos?
En lugar de hacer esto:
enum Foo {
BAR = 60,
EVERYTHING_IS_TERRIBLE = 80
}
console.log(Object.keys(Foo))
// -> ["60", "80", "BAR", "EVERYTHING_IS_TERRIBLE"]
console.log(Object.values(Foo))
// -> ["BAR", "EVERYTHING_IS_TERRIBLE", 60, 80]
Haz esto (presta atención al as const
elenco):
const Foo = {
BAR: 60,
EVERYTHING_IS_TERRIBLE: 80
} as const
console.log(Object.keys(Foo))
// -> ["BAR", "EVERYTHING_IS_TERRIBLE"]
console.log(Object.values(Foo))
// -> [60, 80]
console.log(Object.keys(Foo))
en el primer ejemplo solo regresa ["BAR", "EVERYTHING_IS_TERRIBLE"]
..
["60", "80", "BAR", "EVERYTHING_IS_TERRIBLE"]
Encontré esta pregunta buscando "TypeScript iterate over enum keys". Así que solo quiero publicar una solución que funcione para mí en mi caso. Quizás también ayude a alguien.
Mi caso es el siguiente: quiero iterar sobre cada clave de enumeración, luego filtrar algunas claves, luego acceder a algún objeto que tenga claves como valores calculados de enumeración. Así es como lo hago sin tener ningún error de TS.
enum MyEnum = { ONE = 'ONE', TWO = 'TWO' }
const LABELS = {
[MyEnum.ONE]: 'Label one',
[MyEnum.TWO]: 'Label two'
}
// to declare type is important - otherwise TS complains on LABELS[type]
// also, if replace Object.values with Object.keys -
// - TS blames wrong types here: "string[] is not assignable to MyEnum[]"
const allKeys: Array<MyEnum> = Object.values(MyEnum)
const allowedKeys = allKeys.filter(
(type) => type !== MyEnum.ONE
)
const allowedLabels = allowedKeys.map((type) => ({
label: LABELS[type]
}))
Escribí una clase EnumUtil que está haciendo una verificación de tipo por el valor enum:
export class EnumUtils {
/**
* Returns the enum keys
* @param enumObj enum object
* @param enumType the enum type
*/
static getEnumKeys(enumObj: any, enumType: EnumType): any[] {
return EnumUtils.getEnumValues(enumObj, enumType).map(value => enumObj[value]);
}
/**
* Returns the enum values
* @param enumObj enum object
* @param enumType the enum type
*/
static getEnumValues(enumObj: any, enumType: EnumType): any[] {
return Object.keys(enumObj).filter(key => typeof enumObj[key] === enumType);
}
}
export enum EnumType {
Number = 'number',
String = 'string'
}
Cómo usarlo:
enum NumberValueEnum{
A= 0,
B= 1
}
enum StringValueEnum{
A= 'A',
B= 'B'
}
EnumUtils.getEnumKeys(NumberValueEnum, EnumType.number);
EnumUtils.getEnumValues(NumberValueEnum, EnumType.number);
EnumUtils.getEnumKeys(StringValueEnum, EnumType.string);
EnumUtils.getEnumValues(StringValueEnum, EnumType.string);
Resultado para las teclas NumberValueEnum: ["A", "B"]
Resultado para los valores NumberValueEnum: [0, 1]
Resultado para StringValueEnumkeys: ["A", "B"]
Resultado para StringValueEnumvalues: ["A", "B"]
Encuentro esa solución más elegante:
for (let val in myEnum ) {
if ( isNaN( parseInt( val )) )
console.log( val );
}
Muestra:
bar
foo
Mi enumeración es así:
export enum UserSorting {
SortByFullName = "Sort by FullName",
SortByLastname = "Sort by Lastame",
SortByEmail = "Sort by Email",
SortByRoleName = "Sort by Role",
SortByCreatedAt = "Sort by Creation date",
SortByCreatedBy = "Sort by Author",
SortByUpdatedAt = "Sort by Edit date",
SortByUpdatedBy = "Sort by Editor",
}
haciendo este retorno indefinido :
UserSorting[UserSorting.SortByUpdatedAt]
Para resolver este problema, elijo otra forma de hacerlo usando una tubería:
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'enumKey'
})
export class EnumKeyPipe implements PipeTransform {
transform(value, args: string[] = null): any {
let enumValue = args[0];
var keys = Object.keys(value);
var values = Object.values(value);
for (var i = 0; i < keys.length; i++) {
if (values[i] == enumValue) {
return keys[i];
}
}
return null;
}
}
Y para usarlo:
return this.enumKeyPipe.transform(UserSorting, [UserSorting.SortByUpdatedAt]);
Si tienes enumeracion
enum Diet {
KETO = "Ketogenic",
ATKINS = "Atkins",
PALEO = "Paleo",
DGAF = "Whatever"
}
Entonces puede obtener claves y valores como:
Object.keys(Diet).forEach((d: Diet) => {
console.log(d); // KETO
console.log(Diet[d]) // Ketogenic
});
Argument of type '(d: Diet) => void' is not assignable to parameter of type '(value: string, index: number, array: string[]) => void'. Types of parameters 'd' and 'value' are incompatible. Type 'string' is not assignable to type 'MyEnum'.(2345)
Escribí una función auxiliar para enumerar una enumeración:
static getEnumValues<T extends number>(enumType: {}): T[] {
const values: T[] = [];
const keys = Object.keys(enumType);
for (const key of keys.slice(0, keys.length / 2)) {
values.push(<T>+key);
}
return values;
}
Uso:
for (const enumValue of getEnumValues<myEnum>(myEnum)) {
// do the thing
}
La función devuelve algo que se puede enumerar fácilmente y también se convierte al tipo de enumeración.
Con una versión actual de TypeScript, puede utilizar funciones como estas para asignar la enumeración a un registro de su elección. Tenga en cuenta que no puede definir valores de cadena con estas funciones, ya que buscan claves con un valor que sea un número.
enum STATES {
LOGIN,
LOGOUT,
}
export const enumToRecordWithKeys = <E extends any>(enumeration: E): E => (
Object.keys(enumeration)
.filter(key => typeof enumeration[key] === 'number')
.reduce((record, key) => ({...record, [key]: key }), {}) as E
);
export const enumToRecordWithValues = <E extends any>(enumeration: E): E => (
Object.keys(enumeration)
.filter(key => typeof enumeration[key] === 'number')
.reduce((record, key) => ({...record, [key]: enumeration[key] }), {}) as E
);
const states = enumToRecordWithKeys(STATES)
const statesWithIndex = enumToRecordWithValues(STATES)
console.log(JSON.stringify({
STATES,
states,
statesWithIndex,
}, null ,2));
// Console output:
{
"STATES": {
"0": "LOGIN",
"1": "LOGOUT",
"LOGIN": 0,
"LOGOUT": 1
},
"states": {
"LOGIN": "LOGIN",
"LOGOUT": "LOGOUT"
},
"statesWithIndex": {
"LOGIN": 0,
"LOGOUT": 1
}
}
Ya hay muchas respuestas aquí, pero creo que arrojaré mi solución a la pila de todos modos.
enum AccountType {
Google = 'goo',
Facebook = 'boo',
Twitter = 'wit',
}
type Key = keyof typeof AccountType // "Google" | "Facebook" | "Twitter"
// this creates a POJO of the enum "reversed" using TypeScript's Record utility
const reversed = (Object.keys(AccountType) as Key[]).reduce((acc, key) => {
acc[AccountType[key]] = key
return acc
}, {} as Record<AccountType, string>)
Para mayor claridad:
/*
* reversed == {
* "goo": "Google",
* "boo": "Facebook",
* "wit": "Twitter",
* }
* reversed[AccountType.Google] === "Google" 👍
*/
Referencia para el registro de TypeScript
Una buena función auxiliar:
const getAccountTypeName = (type: AccountType) => {
return reversed[type]
};
// getAccountTypeName(AccountType.Twitter) === 'Twitter'
No es exactamente la respuesta de su pregunta, pero es un truco para abordar su problema.
export module Gender {
export enum Type {
Female = 1,
Male = 2
};
export const List = Object.freeze([
Type[Type.Female] ,
Type[Type.Male]
]);
}
Puede ampliar su modelo de lista de la forma que desee.
export const List = Object.freeze([
{ name: Type[Type.Female], value: Type.Female } ,
{ name: Type[Type.Male], value: Type.Male }
]);
Ahora, puede usarlo de esta manera:
for(const gender of Gender.List){
console.log(gender.name);
console.log(gender.value);
}
o:
if(i === Gender.Type.Male){
console.log("I am a man.");
}
getAllEnumValues
ygetAllEnumKeys
para su propósito