Gostaria de repetir um TypeScript enum
e obter um nome de símbolo enumerado, por exemplo:
enum myEnum { entry1, entry2 }
for (var entry in myEnum) {
// use entry's name here, e.g., "entry1"
}
Gostaria de repetir um TypeScript enum
e obter um nome de símbolo enumerado, por exemplo:
enum myEnum { entry1, entry2 }
for (var entry in myEnum) {
// use entry's name here, e.g., "entry1"
}
Respostas:
O código que você postou funcionará; ele imprimirá todos os membros da enum, incluindo os valores dos membros da enum. Por exemplo, o seguinte código:
enum myEnum { bar, foo }
for (var enumMember in myEnum) {
console.log("enum member: ", enumMember);
}
Irá imprimir o seguinte:
Enum member: 0
Enum member: 1
Enum member: bar
Enum member: foo
Se você preferir apenas os nomes dos membros, e não os valores, poderá fazer algo assim:
for (var enumMember in myEnum) {
var isValueProperty = parseInt(enumMember, 10) >= 0
if (isValueProperty) {
console.log("enum member: ", myEnum[enumMember]);
}
}
Isso imprimirá apenas os nomes:
Membro da enum: bar
Membro da enum: foo
Advertência: isso depende um pouco de detalhes da implementação: o TypeScript compila enumerações em um objeto JS com os valores de enumeração sendo membros do objeto. Se a TS decidir implementá-los de maneira diferente no futuro, a técnica acima poderá ser interrompida.
+enumMember >= 0
deveria ser isFinite(+enumMember)
porque os valores negativos ou de ponto flutuante também são mapeados inversamente. ( Playground )
Embora a resposta já seja fornecida, quase ninguém apontou os documentos
Aqui está um trecho
enum Enum {
A
}
let nameOfA = Enum[Enum.A]; // "A"
Lembre-se de que os membros da string enum não recebem um mapeamento reverso.
0
ou a 1
partir desta enumeração? export enum Octave { ZERO = 0, ONE = 1 }
enum Enum {"A"}; let nameOfA = Enum[Enum.A];
:? A partir de typescript@2.9.2 ele funciona muito bem para mim ...
Supondo que você se atenha às regras e produza apenas enumerações com valores numéricos, você pode usar esse código. Isso lida corretamente com o caso em que você tem um nome que é coincidentemente um 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 mim, uma maneira mais fácil, prática e direta de entender o que está acontecendo, é a seguinte enumeração:
enum colors { red, green, blue };
Será convertido essencialmente para isso:
var colors = { red: 0, green: 1, blue: 2,
[0]: "red", [1]: "green", [2]: "blue" }
Por isso, o seguinte será verdadeiro:
colors.red === 0
colors[colors.red] === "red"
colors["red"] === 0
Isso cria uma maneira fácil de obter o nome de um enumerado da seguinte maneira:
var color: colors = colors.red;
console.log("The color selected is " + colors[color]);
Ele também cria uma boa maneira de converter uma string em um valor enumerado.
var colorName: string = "green";
var color: colors = colors.red;
if (colorName in colors) color = colors[colorName];
As duas situações acima são muito mais comuns, porque geralmente você está muito mais interessado no nome de um valor específico e na serialização de valores de maneira genérica.
Se você pesquisar apenas os nomes e iterar posteriormente, 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 }; });
Com a versão 1.8.9 do TypeScript atual, uso Enums digitadas:
export enum Option {
OPTION1 = <any>'this is option 1',
OPTION2 = <any>'this is option 2'
}
com resultados neste objeto Javascript:
Option = {
"OPTION1": "this is option 1",
"OPTION2": "this is option 2",
"this is option 1": "OPTION1",
"this is option 2": "OPTION2"
}
então eu tenho que consultar através de chaves e valores e retornar apenas 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]]);
}
}
}
E eu recebo as chaves de opção em uma matriz:
optionNames = [ "OPTION1", "OPTION2" ];
A partir do TypeScript 2.4, as enumerações podem conter inicializadores de string https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html
Isso permite que você escreva:
enum Order {
ONE = "First",
TWO = "Second"
}
console.log(`One is ${Order.ONE.toString()}`);
e obtenha esta saída:
Um é o primeiro
Outra solução interessante encontrada aqui é usar o 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']
]);
USAR
console.log(TypeLabel.get(Type.low)); // Low Season
Deixe ts-enum-util
( github , npm ) fazer o trabalho para você e forneça muitos utilitários seguros para tipos adicionais. Funciona com enumerações de seqüência de caracteres e numéricas, ignorando corretamente as entradas de pesquisa inversa de índice numérico para enumerações numéricas:
String enum:
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();
Enumeração 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 do TypeScript 2.4, a enumeração não continha mais a chave como membro. fonte do leia-me TypeScript
A ressalva é que as enumerações inicializadas por string não podem ser mapeadas reversamente para obter o nome do membro da enumeração original. Em outras palavras, você não pode escrever Colors ["RED"] para obter a string "Red".
Minha solução:
export const getColourKey = (value: string ) => {
let colourKey = '';
for (const key in ColourEnum) {
if (value === ColourEnum[key]) {
colourKey = key;
break;
}
}
return colourKey;
};
Você pode usar o enum-values
pacote que escrevi quando tive o mesmo problema:
var names = EnumValues.getNames(myEnum);
Com base nas respostas acima, criei esta assinatura de função de segurança de tipo:
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);
o tipo de stringVals
é'entry1' | 'entry2'
(keyof T)[]
vez de keyof T
. Além disso, export
impede que o seu playground funcione.
Parece que nenhuma das respostas aqui funcionará com enumerações de caracteres em strict
-mode.
Considere enum como:
enum AnimalEnum {
dog = "dog", cat = "cat", mouse = "mouse"
}
Acessando isso com AnimalEnum["dog"]
pode resultar em um erro como:
Element implicitly has an 'any' type because expression of type 'any' can't be used to index type 'typeof AnimalEnum'.ts(7053)
.
Solução adequada para esse caso, escreva-o como:
AnimalEnum["dog" as keyof typeof AnimalEnum]
keyof
with typeof
! Outra solução parece bastante opaca, mas, afinal, acho que o Typescript precisa continuar melhorando no DX - Experiência do desenvolvedor para Enum
De acordo com a documentação do TypeScript, podemos fazer isso via Enum com funções estáticas.
Obter nome de enumeração com funções 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 ler mais sobre o Enum com função estática, siga o link abaixo https://basarat.gitbooks.io/typescript/docs/enums.html
A única solução que funciona para mim em todos os casos (mesmo que os valores sejam cadeias) é a seguinte:
var enumToString = function(enumType, enumValue) {
for (var enumMember in enumType) {
if (enumType[enumMember]==enumValue) return enumMember
}
}
Pergunta antiga, mas, por que não usar um const
mapa de objetos?
Em vez de fazer isso:
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]
Faça isso (preste atenção ao 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))
no primeiro exemplo apenas retornos ["BAR", "EVERYTHING_IS_TERRIBLE"]
..
["60", "80", "BAR", "EVERYTHING_IS_TERRIBLE"]
Encontrei essa pergunta pesquisando "TypeScript iterate over enum keys". Então, eu só quero postar uma solução que funcione para mim no meu caso. Talvez ajude alguém também.
Meu caso é o seguinte: quero iterar sobre cada chave enum, filtrar algumas chaves e acessar algum objeto que possua chaves como valores calculados a partir de enum. Então é assim que eu faço sem nenhum erro 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]
}))
Eu escrevi uma classe EnumUtil que está fazendo uma verificação de tipo pelo 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'
}
Como usá-lo:
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 as chaves NumberValueEnum: ["A", "B"]
Resultado para os valores NumberValueEnum: [0, 1]
Resultado para StringValueEnumkeys: ["A", "B"]
Resultado para StringValueEnumvalues: ["A", "B"]
Acho essa solução mais elegante:
for (let val in myEnum ) {
if ( isNaN( parseInt( val )) )
console.log( val );
}
Exibe:
bar
foo
Meu Enum é assim:
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",
}
fazendo esse retorno indefinido :
UserSorting[UserSorting.SortByUpdatedAt]
Para resolver esse problema, escolho outra maneira de fazer isso usando um Pipe:
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;
}
}
E para usá-lo:
return this.enumKeyPipe.transform(UserSorting, [UserSorting.SortByUpdatedAt]);
Se você tem enum
enum Diet {
KETO = "Ketogenic",
ATKINS = "Atkins",
PALEO = "Paleo",
DGAF = "Whatever"
}
Então você pode obter chave e 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)
Eu escrevi uma função auxiliar para enumerar uma enumeração:
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
}
A função retorna algo que pode ser facilmente enumerado e também é convertido para o tipo de enumeração.
Usando uma versão atual do TypeScript, você pode usar funções como estas para mapear o Enum para um registro de sua escolha. Observe que você não pode definir valores de sequência com essas funções, pois elas procuram chaves com um valor que é um 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
}
}
Já existem muitas respostas aqui, mas acho que jogarei minha solução na pilha de qualquer maneira.
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 maior clareza:
/*
* reversed == {
* "goo": "Google",
* "boo": "Facebook",
* "wit": "Twitter",
* }
* reversed[AccountType.Google] === "Google" 👍
*/
Referência para registro TypeScript
Uma boa função auxiliar:
const getAccountTypeName = (type: AccountType) => {
return reversed[type]
};
// getAccountTypeName(AccountType.Twitter) === 'Twitter'
Não é exatamente a resposta da sua pergunta, mas é um truque para resolver o seu problema.
export module Gender {
export enum Type {
Female = 1,
Male = 2
};
export const List = Object.freeze([
Type[Type.Female] ,
Type[Type.Male]
]);
}
Você pode estender seu modelo de lista da maneira que desejar.
export const List = Object.freeze([
{ name: Type[Type.Female], value: Type.Female } ,
{ name: Type[Type.Male], value: Type.Male }
]);
Agora, você pode usá-lo desta maneira:
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
egetAllEnumKeys
para o seu propósito