Esta es la salida de JavaScript de esa enumeración:
var MyEnum;
(function (MyEnum) {
MyEnum[MyEnum["First"] = 0] = "First";
MyEnum[MyEnum["Second"] = 1] = "Second";
MyEnum[MyEnum["Third"] = 2] = "Third";
})(MyEnum || (MyEnum = {}));
Que es un objeto como este:
{
"0": "First",
"1": "Second",
"2": "Third",
"First": 0,
"Second": 1,
"Third": 2
}
Miembros de enumeración con valores de cadena
TypeScript 2.4 agregó la capacidad para que las enumeraciones posiblemente tengan valores de miembro de enumeración de cadena. Entonces, es posible terminar con una enumeración similar a la siguiente:
enum MyEnum {
First = "First",
Second = 2,
Other = "Second"
}
var MyEnum;
(function (MyEnum) {
MyEnum["First"] = "First";
MyEnum[MyEnum["Second"] = 2] = "Second";
MyEnum["Other"] = "Second";
})(MyEnum || (MyEnum = {}));
Obtener nombres de miembros
Podemos ver el ejemplo inmediatamente anterior para tratar de averiguar cómo obtener los miembros enum:
{
"2": "Second",
"First": "First",
"Second": 2,
"Other": "Second"
}
Esto es lo que se me ocurrió:
const e = MyEnum as any;
const names = Object.keys(e).filter(k =>
typeof e[k] === "number"
|| e[k] === k
|| e[e[k]]?.toString() !== k
);
Valores de los miembros
Una vez que tenemos los nombres, podemos recorrerlos para obtener el valor correspondiente haciendo:
const values = names.map(k => MyEnum[k]);
Clase de extensión
Creo que la mejor manera de hacer esto es crear sus propias funciones (ej. EnumEx.getNames(MyEnum)
). No puede agregar una función a una enumeración.
class EnumEx {
private constructor() {
}
static getNamesAndValues(e: any) {
return EnumEx.getNames(e).map(n => ({ name: n, value: e[n] as string | number }));
}
static getNames(e: any) {
return Object.keys(e).filter(k =>
typeof e[k] === "number"
|| e[k] === k
|| e[e[k]]?.toString() !== k
);
}
static getValues(e: any) {
return EnumEx.getNames(e).map(n => e[n] as string | number);
}
}
for of
declaración en lugar de unafor in
Con TypeScript> = 2.4 puede definir enumeraciones de cadena:
enum Color { RED = 'Red', ORANGE = 'Orange', YELLOW = 'Yellow', GREEN = 'Green', BLUE = 'Blue', INDIGO = 'Indigo', VIOLET = 'Violet' }
Salida de JavaScript ES5:
var Color; (function (Color) { Color["RED"] = "Red"; Color["ORANGE"] = "Orange"; Color["YELLOW"] = "Yellow"; Color["GREEN"] = "Green"; Color["BLUE"] = "Blue"; Color["INDIGO"] = "Indigo"; Color["VIOLET"] = "Violet"; })(Color || (Color = {}));
Que es un objeto como este:
const Color = { "RED": "Red", "ORANGE": "Orange", "YELLOW": "Yellow", "GREEN": "Green", "BLUE": "Blue", "INDIGO": "Indigo", "VIOLET": "Violet" }
Por lo tanto, en el caso de enumeraciones de cadenas, no es necesario filtrar cosas,
Object.keys(Color)
yObject.values(Color)
(*) son suficientes:const colorKeys = Object.keys(Color) as (keyof typeof Color)[]; console.log('colorKeys =', colorKeys); // ["RED", "ORANGE", "YELLOW", "GREEN", "BLUE", "INDIGO", "VIOLET"] const colorValues = Object.values(Color); console.log('colorValues =', colorValues); // ["Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet"] colorKeys.map(colorKey => { console.log(`color key = ${colorKey}, value = ${Color[colorKey]}`); }); /* color key = RED, value = Red color key = ORANGE, value = Orange color key = YELLOW, value = Yellow color key = GREEN, value = Green color key = BLUE, value = Blue color key = INDIGO, value = Indigo color key = VIOLET, value = Violet */
Ver ejemplo en línea en el patio de juegos de TypeScript
(*) Polyfill necesario para navegadores antiguos, consulte https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Object/values#Browser_compatibility
fuente
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'typeof Color'. No index signature with a parameter of type 'string' was found on type 'typeof Color'.
Object.keys(Color) as (keyof typeof Color)[]
Puede agregar funciones para obtener los nombres y los índices de la enumeración:
enum MyEnum { First, Second, Third } namespace MyEnum { function isIndex(key):boolean { const n = ~~Number(key); return String(n) === key && n >= 0; } const _names:string[] = Object .keys(MyEnum) .filter(key => !isIndex(key)); const _indices:number[] = Object .keys(MyEnum) .filter(key => isIndex(key)) .map(index => Number(index)); export function names():string[] { return _names; } export function indices():number[] { return _indices; } } console.log("MyEnum names:", MyEnum.names()); // Prints: MyEnum names: ["First", "Second", "Third"] console.log("MyEnum indices:", MyEnum.indices()); // Prints: MyEnum indices: [0, 1, 2]
Tenga en cuenta que podría exportar las consts
_names
y en_indices
lugar de exponerlas a través de una función exportada, pero debido a que los miembros exportados son miembros de la enumeración, podría decirse que es más claro tenerlos como funciones para que no se confundan con los miembros reales de la enumeración.Sería bueno si TypeScript generara algo como esto automáticamente para todas las enumeraciones.
fuente
No existe un concepto de RTTI (información de tipo de tiempo de ejecución) en TypeScript (piense: reflexión), por lo que para hacer esto, se requiere conocimiento del JavaScript transpilado. Entonces, asumiendo TypeScript 0.95:
se convierte en:
var MyEnum; (function(MyEnum) { MyEnum[MyEnum["First"] = 0] = "First"; MyEnum[MyEnum["Second"] = 1] = "Second"; MyEnum[MyEnum["Third"] = 2] = "Third"; }
Entonces, esto se modela como un objeto regular en javascript, donde
MyEnum.0 == "First"
yMyEnum.First == 0
. Entonces, para enumerar todos los nombres de enumeración, debe obtener todas las propiedades que pertenecen al objeto y que tampoco son números:for (var prop in MyEnum) { if (MyEnum.hasOwnProperty(prop) && (isNaN(parseInt(prop)))) { console.log("name: " + prop); } }
Ok, ahora que te he dicho cómo hacerlo, puedo decirte que es una mala idea . No está escribiendo un idioma administrado, por lo que no puede incorporar estos hábitos. Todavía es simplemente JavaScript antiguo. Si quisiera usar una estructura en JavaScript para completar algún tipo de lista de opciones, usaría una matriz antigua simple. Una enumeración no es la elección correcta aquí, juego de palabras. El objetivo de TypeScript es generar JavaScript bonito e idiomático. El uso de enumeraciones de esta manera no preserva este objetivo.
fuente
Usé la solución propuesta por David Sherret y escribí una biblioteca npm que puede usar con el nombre
enum-values
...Git: valores de enumeración
// Suppose we have an enum enum SomeEnum { VALUE1, VALUE2, VALUE3 } // names will be equal to: ['VALUE1', 'VALUE2', 'VALUE3'] var names = EnumValues.getNames(SomeEnum); // values will be equal to: [0, 1, 2] var values = EnumValues.getValues(SomeEnum);
fuente
Una línea de una sola línea para obtener una lista de entradas (objetos / pares clave-valor):
Object.keys(MyEnum).filter(a=>a.match(/^\D/)).map(name=>({name, value: MyEnum[name] as number}));
fuente
enum MyEnum { First, Second, Third, NUM_OF_ENUMS } for(int i = 0; i < MyEnum.NUM_OF_ENUMS; ++i) { // do whatever you need to do. }
fuente
Si desea asociar valores de cadenas a su enumeración, estos métodos no funcionan. Para tener una función genérica puedes hacer:
function listEnum(enumClass) { var values = []; for (var key in enumClass) { values.push(enum[key]); } values.length = values.length / 2; return values; }
Funciona porque TypeScript agregará claves en el primer paso y valores en el segundo.
En TypeScript es:
var listEnums = <T> (enumClass: any): T[]=> { var values: T[] = []; for (var key in enumClass) { values.push(enumClass[key]); } values.length = values.length / 2; return values; }; var myEnum: TYPE[] = listEnums<TYPE>(TYPE);
fuente
La respuesta de Joe me hizo darme cuenta de que es mucho más fácil confiar en las primeras N teclas numéricas que hacer pruebas más complejas:
function getEnumMembers(myEnum): string[] { let members = [] for(let i:number = 0; true; i++) { if(myEnum[i] === undefined) break members.push(myEnum[i]) } return members } enum Colors { Red, Green, Blue } console.log(getEnumMembers(myEnum))
fuente
para nodejs:
const { isNumber } = require('util'); Object.values(EnumObject) .filter(val => isNumber(val)) .map(val => { // do your stuff })
fuente
Iterando sobre una enumeración
Las enumeraciones de cadena se utilizan mejor para esto. Aquí hay un ejemplo:
// This is a string enum enum MyEnum { First = 'First', Second = 'Second', Third = 'Third', } // An enum is a TS concept // However his MyEnum compiles to JS object: // { // "First": "First", // "Second": "Second", // "Third": "Third" // } // Therefore we can get the keys in the following manner: const keysArray = Object.keys(MyEnum); for (const key of keysArray) { console.log(key) } // [LOG]: "First" // [LOG]: "Second" // [LOG]: "Third"
fuente