Comment énumérer par programmation un type enum dans TypeScript 0.9.5?

Disons que je possède une énumération TypeScript, MyEnum, comme suit:

enum MyEnum { First, Second, Third } 

Quel serait le meilleur moyen dans TypeScript 0.9.5 pour produire un tableau des valeurs enum? Exemple:

 var choices: MyEnum[]; // or Array choices = MyEnum.GetValues(); // plans for this? choices = EnumEx.GetValues(MyEnum); // or, how to roll my own? 

Ceci est 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 object comme celui-ci:

 Object { 0: "First", 1: "Second", 2: "Third", First: 0, Second: 1, Third: 2 } 

Noms de membres

Pour obtenir les noms des membres enum, nous pouvons filtrer les clés de l’object lorsque la valeur correspondante est un nombre. Cela garantit que les noms ayant la même valeur seront trouvés:

 const names = Object.keys(MyEnum) .filter(k => typeof MyEnum[k] === "number") as ssortingng[]; 

Contient: ["First", "Second", "Third"]

Valeurs membres

Alors que pour obtenir les valeurs des membres enum, nous pouvons filtrer les valeurs de l’object par tout ce qui est un nombre:

 const values = Object.keys(MyEnum) .map(k => MyEnum[k]) .filter(v => typeof v === "number") as number[]; 

Contient: [0, 1, 2]

Classe d’extension

Je pense que la meilleure façon de le faire est de créer vos propres fonctions (ex. EnumEx.getNames(MyEnum) ). Vous ne pouvez pas append une fonction à une énumération.

 class EnumEx { private constructor() { } static getNamesAndValues(e: any) { return EnumEx.getNames(e).map(n => ({ name: n, value: e[n] as T })); } static getNames(e: any) { return Object.keys(e).filter(k => typeof e[k] === "number") as ssortingng[]; } static getValues(e: any) { return Object.keys(e) .map(k => e[k]) .filter(v => typeof v === "number") as T[]; } } 

Avec TypeScript> = 2.4, vous pouvez définir des énumérations de chaîne:

 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 object 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, il n’est pas nécessaire de filtrer les objects, Object.keys(Color) et Object.values(Color) (*) suffisent:

 const colorKeys = Object.keys(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

Il n’y a pas de concept de RTTI (informations de type à l’exécution) dans TypeScript (pensez: reflection). Pour ce faire, vous devez connaître le JavaScript transstackd. Donc, en supposant TypeScript 0.95:

 enum MyEnum { First, Second, Third } 

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 object régulier en javascript, où MyEnum.0 == "First" et MyEnum.First == 0 . Donc, pour énumérer tous les noms d’énumération, vous devez obtenir toutes les propriétés qui appartiennent à l’object 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 un langage géré, vous ne pouvez donc pas apporter ces habitudes. C’est encore du vieux JavaScript. Si je voulais utiliser une structure en JavaScript pour remplir une sorte de liste de choix, j’utiliserais un vieux tableau simple. Un enum n’est pas le bon choix ici, jeu de mots. Le but de TypeScript est de générer du code JavaScript idiomatique. Utiliser les énumérations de cette manière ne préserve pas cet objective.

Vous pouvez append des fonctions pour obtenir les noms et les index de l’énumération:

 enum MyEnum { First, Second, Third } namespace MyEnum { function isIndex(key):boolean { const n = ~~Number(key); return Ssortingng(n) === key && n >= 0; } const _names:ssortingng[] = Object .keys(MyEnum) .filter(key => !isIndex(key)); const _indices:number[] = Object .keys(MyEnum) .filter(key => isIndex(key)) .map(index => Number(index)); export function names():ssortingng[] { 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 au lieu de les exposer via une fonction exscope, mais comme les membres exportés sont membres de l’énum, ​​il est plus clair de les avoir comme fonctions afin de ne pas les confondre avec les membres enum réels.

Ce serait bien si TypeScript générait automatiquement quelque chose comme ça pour toutes les énumérations.

J’ai utilisé la solution proposée par David Sherret et j’ai écrit une bibliothèque npm que vous pouvez utiliser 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); 
 enum MyEnum { First, Second, Third, NUM_OF_ENUMS } for(int i = 0; i < MyEnum.NUM_OF_ENUMS; ++i) { // do whatever you need to do. } 

Si vous souhaitez associer des valeurs de chaînes à votre enum, 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 parce que TypeScript appenda des clés dans la première étape et des valeurs dans la deuxième étape.

En TypeScript c’est:

 var listEnums =  (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); 

La réponse de Joe m’a fait comprendre qu’il est beaucoup plus facile de compter sur les N premières touches numériques que de faire des tests plus complexes:

 function getEnumMembers(myEnum): ssortingng[] { 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)) 

Un one-liner pour obtenir une liste des entrées (objects / paires clé-valeur):

 Object.keys(MyEnum).filter(a=>a.match(/^\D/)).map(name=>({name, value: MyEnum[name] as number}));