Je voudrais itérer un TypeScript un enum
type et obtenir chaque nom de symbole énuméré, par exemple:
enum myEnum { entry1, entry2 }
for (var entry in myEnum) {
// use entry's name here, e.g., "entry1"
}
Je voudrais itérer un TypeScript un enum
type et obtenir chaque nom de symbole énuméré, par exemple:
enum myEnum { entry1, entry2 }
for (var entry in myEnum) {
// use entry's name here, e.g., "entry1"
}
Réponses:
Le code que vous avez publié fonctionnera; il imprimera tous les membres de l'énumération, y compris les valeurs des membres de l'énumération. Par exemple, le code suivant:
enum myEnum { bar, foo }
for (var enumMember in myEnum) {
console.log("enum member: ", enumMember);
}
Imprime ce qui suit:
Enum member: 0
Enum member: 1
Enum member: bar
Enum member: foo
Si vous ne souhaitez que les noms de membres et non les valeurs, vous pouvez faire quelque chose comme ceci:
for (var enumMember in myEnum) {
var isValueProperty = parseInt(enumMember, 10) >= 0
if (isValueProperty) {
console.log("enum member: ", myEnum[enumMember]);
}
}
Cela n'imprimera que les noms:
Membre enum: bar
Membre enum: foo
Avertissement: cela s'appuie légèrement sur un détail d'implémentation: TypeScript compile les énumérations en un objet JS avec les valeurs d'énumération membres de l'objet. Si TS décidait de les implémenter différemment à l'avenir, la technique ci-dessus pourrait échouer.
+enumMember >= 0
devrait être isFinite(+enumMember)
dû au fait que les valeurs négatives ou à virgule flottante sont également inversées. ( Aire de jeux )
Bien que la réponse soit déjà fournie, presque personne n'a pointé les documents
Voici un extrait
enum Enum {
A
}
let nameOfA = Enum[Enum.A]; // "A"
Gardez à l'esprit que les membres d'énumération de chaîne n'obtiennent pas du tout de mappage inverse.
0
ou 1
de cette énumération? export enum Octave { ZERO = 0, ONE = 1 }
enum Enum {"A"}; let nameOfA = Enum[Enum.A];
? À partir de typescript@2.9.2 cela fonctionne très bien pour moi ...
En supposant que vous respectiez les règles et ne produisiez que des énumérations avec des valeurs numériques, vous pouvez utiliser ce code. Cela gère correctement le cas où vous avez un nom qui est par coïncidence un nombre valide
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']
Pour moi, une façon plus simple, pratique et directe de comprendre ce qui se passe, c'est que l'énumération suivante:
enum colors { red, green, blue };
Sera converti essentiellement en ceci:
var colors = { red: 0, green: 1, blue: 2,
[0]: "red", [1]: "green", [2]: "blue" }
Pour cette raison, ce qui suit sera vrai:
colors.red === 0
colors[colors.red] === "red"
colors["red"] === 0
Cela crée un moyen facile d'obtenir le nom d'un énuméré comme suit:
var color: colors = colors.red;
console.log("The color selected is " + colors[color]);
Il crée également un bon moyen de convertir une chaîne en une valeur énumérée.
var colorName: string = "green";
var color: colors = colors.red;
if (colorName in colors) color = colors[colorName];
Les deux situations ci-dessus sont une situation beaucoup plus courante, car généralement vous êtes beaucoup plus intéressé par le nom d'une valeur spécifique et la sérialisation des valeurs de manière générique.
Si vous recherchez uniquement les noms et que vous réitérez ultérieurement, utilisez:
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 }; });
Avec la version 1.8.9 de TypeScript actuelle, j'utilise des énumérations typées:
export enum Option {
OPTION1 = <any>'this is option 1',
OPTION2 = <any>'this is option 2'
}
avec des résultats dans cet objet Javascript:
Option = {
"OPTION1": "this is option 1",
"OPTION2": "this is option 2",
"this is option 1": "OPTION1",
"this is option 2": "OPTION2"
}
donc je dois interroger les clés et les valeurs et ne retourner que les valeurs:
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]]);
}
}
}
Et je reçois les clés d'option dans un tableau:
optionNames = [ "OPTION1", "OPTION2" ];
Depuis TypeScript 2.4, les énumérations peuvent contenir des initialiseurs de chaîne https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html
Cela vous permet d'écrire:
enum Order {
ONE = "First",
TWO = "Second"
}
console.log(`One is ${Order.ONE.toString()}`);
et obtenez cette sortie:
On est premier
Une autre solution intéressante trouvée ici utilise 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']
]);
UTILISATION
console.log(TypeLabel.get(Type.low)); // Low Season
Laissez ts-enum-util
( github , npm ) faire le travail pour vous et fournissez de nombreux utilitaires de type sécurisé supplémentaires. Fonctionne avec les énumérations de chaîne et numériques, en ignorant correctement les entrées de recherche inversée d'index numérique pour les énumérations numériques:
Énumération des chaînes:
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();
Énumération numérique:
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();
À partir de TypeScript 2.4, l'énumération ne contiendrait plus la clé en tant que membre. source du fichier Lisez-moi TypeScript
La mise en garde est que les énumérations initialisées par une chaîne ne peuvent pas être mappées en sens inverse pour obtenir le nom de membre de l'énumération d'origine. En d'autres termes, vous ne pouvez pas écrire Couleurs ["ROUGE"] pour obtenir la chaîne "Rouge".
Ma solution:
export const getColourKey = (value: string ) => {
let colourKey = '';
for (const key in ColourEnum) {
if (value === ColourEnum[key]) {
colourKey = key;
break;
}
}
return colourKey;
};
Vous pouvez utiliser le enum-values
package que j'ai écrit lorsque j'ai eu le même problème:
var names = EnumValues.getNames(myEnum);
Sur la base de certaines réponses ci-dessus, j'ai trouvé cette signature de fonction de type sécurisé:
export function getStringValuesFromEnum<T>(myEnum: T): keyof T {
return Object.keys(myEnum).filter(k => typeof (myEnum as any)[k] === 'number') as any;
}
Usage:
enum myEnum { entry1, entry2 };
const stringVals = getStringValuesFromEnum(myEnum);
le type de stringVals
est'entry1' | 'entry2'
(keyof T)[]
au lieu de keyof T
. De plus, cela export
empêche votre terrain de jeu de fonctionner.
Il semble qu'aucune des réponses ici ne fonctionnera avec des strict
énumérations de chaînes en mode.
Considérez enum comme:
enum AnimalEnum {
dog = "dog", cat = "cat", mouse = "mouse"
}
Accéder à cela avec AnimalEnum["dog"]
peut entraîner une erreur comme:
Element implicitly has an 'any' type because expression of type 'any' can't be used to index type 'typeof AnimalEnum'.ts(7053)
.
Solution appropriée pour ce cas, écrivez-la comme suit:
AnimalEnum["dog" as keyof typeof AnimalEnum]
keyof
avec typeof
! Une autre solution semble assez opaque, mais après tout, je pense que Typescript doit continuer à s'améliorer sur DX - Developer Experience for Enum
La meilleure façon, je pense, est de simplement déclarer les valeurs d'énumération souhaitées. De cette façon, y accéder est propre et joli (à chaque fois).
enum myEnum { entry1 = 'VALUE1', entry2 = 'VALUE2' }
for (var entry in myEnum) {
console.log(entry);
}
produira:
VALUE1
VALUE2
Selon la documentation TypeScript, nous pouvons le faire via Enum avec des fonctions statiques.
Obtenir un nom enum avec des fonctions statiques
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
pour en savoir plus sur Enum avec fonction statique, suivez le lien ci-dessous https://basarat.gitbooks.io/typescript/docs/enums.html
La seule solution qui fonctionne pour moi dans tous les cas (même si les valeurs sont des chaînes) est la suivante:
var enumToString = function(enumType, enumValue) {
for (var enumMember in enumType) {
if (enumType[enumMember]==enumValue) return enumMember
}
}
Vieille question, mais pourquoi ne pas utiliser un const
carte d'objets?
Au lieu de faire ceci:
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]
Faites ceci (faites attention à la as const
distribution):
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))
dans le premier exemple ne revient que ["BAR", "EVERYTHING_IS_TERRIBLE"]
..
["60", "80", "BAR", "EVERYTHING_IS_TERRIBLE"]
J'ai trouvé cette question en recherchant "TypeScript itérer sur les clés enum". Je veux donc simplement publier une solution qui fonctionne pour moi dans mon cas. Peut-être que cela aidera aussi quelqu'un.
Mon cas est le suivant: je veux parcourir chaque clé enum, puis filtrer certaines clés, puis accéder à un objet qui a des clés comme valeurs calculées à partir d'énum. Voilà donc comment je le fais sans avoir d'erreur 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]
}))
J'ai écrit une classe EnumUtil qui vérifie le type par la valeur 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'
}
Comment l'utiliser:
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);
Résultat pour les clés NumberValueEnum: ["A", "B"]
Résultat pour les valeurs NumberValueEnum: [0, 1]
Résultat pour StringValueEnumkeys: ["A", "B"]
Résultat pour StringValueEnumvalues: ["A", "B"]
Je trouve cette solution plus élégante:
for (let val in myEnum ) {
if ( isNaN( parseInt( val )) )
console.log( val );
}
Il affiche:
bar
foo
Mon Enum est comme ceci:
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",
}
faisant ce retour non défini :
UserSorting[UserSorting.SortByUpdatedAt]
Pour résoudre ce problème, je choisis une autre façon de le faire à l'aide d'un tuyau:
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;
}
}
Et pour l'utiliser:
return this.enumKeyPipe.transform(UserSorting, [UserSorting.SortByUpdatedAt]);
Si vous avez une énumération
enum Diet {
KETO = "Ketogenic",
ATKINS = "Atkins",
PALEO = "Paleo",
DGAF = "Whatever"
}
Ensuite, vous pouvez obtenir des clés et des valeurs comme:
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)
J'ai écrit une fonction d'aide pour énumérer une énumération:
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;
}
Usage:
for (const enumValue of getEnumValues<myEnum>(myEnum)) {
// do the thing
}
La fonction renvoie quelque chose qui peut être facilement énuméré, et convertit également le type enum.
En utilisant une version actuelle de TypeScript, vous pouvez utiliser des fonctions comme celles-ci pour mapper l'énumération à un enregistrement de votre choix. Notez que vous ne pouvez pas définir de valeurs de chaîne avec ces fonctions car elles recherchent des clés avec une valeur qui est un nombre.
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
}
}
Il y a déjà beaucoup de réponses ici, mais je pense que je vais quand même jeter ma solution sur la pile.
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>)
Pour plus de clarté:
/*
* reversed == {
* "goo": "Google",
* "boo": "Facebook",
* "wit": "Twitter",
* }
* reversed[AccountType.Google] === "Google" 👍
*/
Référence pour enregistrement TypeScript
Une belle fonction d'aide:
const getAccountTypeName = (type: AccountType) => {
return reversed[type]
};
// getAccountTypeName(AccountType.Twitter) === 'Twitter'
Ce n'est pas exactement la réponse à votre question, mais c'est une astuce pour résoudre votre problème.
export module Gender {
export enum Type {
Female = 1,
Male = 2
};
export const List = Object.freeze([
Type[Type.Female] ,
Type[Type.Male]
]);
}
Vous pouvez étendre votre modèle de liste comme vous le souhaitez.
export const List = Object.freeze([
{ name: Type[Type.Female], value: Type.Female } ,
{ name: Type[Type.Male], value: Type.Male }
]);
Maintenant, vous pouvez l'utiliser de cette façon:
for(const gender of Gender.List){
console.log(gender.name);
console.log(gender.value);
}
ou:
if(i === Gender.Type.Male){
console.log("I am a man.");
}
getAllEnumValues
etgetAllEnumKeys
pour votre but