Voici la sortie JavaScript de cette énumération:
var MyEnum;
(function (MyEnum) {
MyEnum[MyEnum["First"] = 0] = "First";
MyEnum[MyEnum["Second"] = 1] = "Second";
MyEnum[MyEnum["Third"] = 2] = "Third";
})(MyEnum || (MyEnum = {}));
Quel est un objet comme celui-ci:
{
"0": "First",
"1": "Second",
"2": "Third",
"First": 0,
"Second": 1,
"Third": 2
}
Énumérer les membres avec des valeurs de chaîne
TypeScript 2.4 a ajouté la possibilité pour les enums d'avoir éventuellement des valeurs de membre enum de chaîne. Il est donc possible de se retrouver avec une énumération qui ressemble à ceci:
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 = {}));
Obtenir les noms des membres
Nous pouvons regarder l'exemple ci-dessus pour essayer de comprendre comment obtenir les membres enum:
{
"2": "Second",
"First": "First",
"Second": 2,
"Other": "Second"
}
Voici ce que j'ai trouvé:
const e = MyEnum as any;
const names = Object.keys(e).filter(k =>
typeof e[k] === "number"
|| e[k] === k
|| e[e[k]]?.toString() !== k
);
Valeurs des membres
Une fois que nous avons les noms, nous pouvons les parcourir pour obtenir la valeur correspondante en faisant:
const values = names.map(k => MyEnum[k]);
Classe d'extension
Je pense que la meilleure façon de faire est de créer vos propres fonctions (ex. EnumEx.getNames(MyEnum)
). Vous ne pouvez pas ajouter de fonction à une énumération.
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
déclaration au lieu d'unfor in
Avec TypeScript> = 2.4, vous pouvez définir des énumérations de chaînes:
enum Color { RED = 'Red', ORANGE = 'Orange', YELLOW = 'Yellow', GREEN = 'Green', BLUE = 'Blue', INDIGO = 'Indigo', VIOLET = 'Violet' }
Sortie 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 = {}));
Quel est un objet comme celui-ci:
const Color = { "RED": "Red", "ORANGE": "Orange", "YELLOW": "Yellow", "GREEN": "Green", "BLUE": "Blue", "INDIGO": "Indigo", "VIOLET": "Violet" }
Ainsi, dans le cas des énumérations de chaînes, pas besoin de filtrer les choses,
Object.keys(Color)
etObject.values(Color)
(*) suffisent: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 */
Voir l' exemple en ligne sur le terrain de jeu TypeScript
(*) Polyfill nécessaire pour les anciens navigateurs, voir https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Object/values#Browser_compatibility
la source
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)[]
Vous pouvez ajouter des fonctions pour obtenir les noms et les indices de l'énumération:
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]
Notez que vous pouvez simplement exporter les
_names
et_indices
consts plutôt que de les exposer via une fonction exportée, mais comme les membres exportés sont des membres de l'énumération, il est sans doute plus clair de les avoir en tant que fonctions afin qu'ils ne soient pas confondus avec les membres enum réels.Ce serait bien si TypeScript générait automatiquement quelque chose comme ça pour toutes les énumérations.
la source
Il n'y a pas de concept de RTTI (informations de type d'exécution) dans TypeScript (pensez: réflexion) donc pour ce faire, la connaissance du JavaScript transpilé est nécessaire. Donc, en supposant TypeScript 0.95:
devient:
var MyEnum; (function(MyEnum) { MyEnum[MyEnum["First"] = 0] = "First"; MyEnum[MyEnum["Second"] = 1] = "Second"; MyEnum[MyEnum["Third"] = 2] = "Third"; }
Donc, ceci est modélisé comme un objet régulier en javascript, où
MyEnum.0 == "First"
etMyEnum.First == 0
. Donc, pour énumérer tous les noms d'énumération, vous devez obtenir toutes les propriétés qui appartiennent à l'objet et qui ne sont pas non plus des nombres:for (var prop in MyEnum) { if (MyEnum.hasOwnProperty(prop) && (isNaN(parseInt(prop)))) { console.log("name: " + prop); } }
Ok, alors maintenant je vous ai dit comment faire, j'ai le droit de vous dire que c'est une mauvaise idée . Vous n'écrivez pas une langue gérée, vous ne pouvez donc pas adopter ces habitudes. C'est toujours juste du vieux JavaScript. Si je voulais utiliser une structure en JavaScript pour remplir une sorte de liste de choix, j'utiliserais un tableau ancien. Une énumération n'est pas le bon choix ici, jeu de mots. Le but de TypeScript est de générer un joli JavaScript idiomatique. L'utilisation d'énumérations de cette manière ne préserve pas cet objectif.
la source
J'ai utilisé la solution proposée par David Sherret et j'ai écrit une bibliothèque npm que vous pouvez utiliser nommée
enum-values
...Git: enum-values
// 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);
la source
Une ligne unique pour obtenir une liste d'entrées (objets / paires clé-valeur):
Object.keys(MyEnum).filter(a=>a.match(/^\D/)).map(name=>({name, value: MyEnum[name] as number}));
la source
enum MyEnum { First, Second, Third, NUM_OF_ENUMS } for(int i = 0; i < MyEnum.NUM_OF_ENUMS; ++i) { // do whatever you need to do. }
la source
Si vous souhaitez associer des valeurs de chaînes à votre énumération, ces méthodes ne fonctionnent pas. Pour avoir une fonction générique, vous pouvez faire:
function listEnum(enumClass) { var values = []; for (var key in enumClass) { values.push(enum[key]); } values.length = values.length / 2; return values; }
Cela fonctionne car TypeScript ajoutera des clés dans la première étape et des valeurs dans la deuxième étape.
Dans TypeScript c'est:
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);
la source
La réponse de Joe m'a juste fait comprendre qu'il est beaucoup plus facile de s'appuyer sur les N premières touches numériques que de faire des tests plus complexes:
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))
la source
pour nodejs:
const { isNumber } = require('util'); Object.values(EnumObject) .filter(val => isNumber(val)) .map(val => { // do your stuff })
la source
Itérer sur une énumération
Les énumérations de chaînes sont mieux utilisées pour cela. Voici un exemple:
// 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"
la source