Compruebe si existe un valor en la enumeración en TypeScript

163

Recibo un número type = 3y tengo que verificar si existe en esta enumeración:

export const MESSAGE_TYPE = {
    INFO: 1,
    SUCCESS: 2,
    WARNING: 3,
    ERROR: 4,
};

La mejor manera que encontré es obtener todos los valores de Enum como una matriz y usar indexOf en él. Pero el código resultante no es muy legible:

if( -1 < _.values( MESSAGE_TYPE ).indexOf( _.toInteger( type ) ) ) {
    // do stuff ...
}

¿Hay una manera más simple de hacer esto?

Tim Schoch
fuente
if(Object.values(MESSAGE_TYPE).includes(+type)? No hay mucho que puedas hacer.
Andrew Li
1
Desafortunadamente
Tim Schoch
@TimSchoch Puede hacer !!MESSAGE_TYPE[type]para verificar si existe un valor. MESSAGE_TYPE[type]volverá indefinido si el valor de typeno existe enMESSAGE_TYPE
Kevin Babcock
1
@Kevin Babcock Sin embargo, eso fallará en uno de los mapas de valores de enumeración 0.
Ingo Bürk
@Ingo Bürk ¡Gran punto! Supongo que se podría hacer una verificación explícitaMESSAGE_TYPE[type] !== undefined
Kevin Babcock

Respuestas:

213

Si desea que esto funcione con enumeraciones de cadenas, debe usarlas Object.values(ENUM).includes(ENUM.value)porque las enumeraciones de cadenas no se asignan de forma inversa, de acuerdo con https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html :

Enum Vehicle {
    Car = 'car',
    Bike = 'bike',
    Truck = 'truck'
}

se convierte en:

{
    Car: 'car',
    Bike: 'bike',
    Truck: 'truck'
}

Entonces solo necesitas hacer:

if (Object.values(Vehicle).includes('car')) {
    // Do stuff here
}

Si obtiene un error para: Property 'values' does not exist on type 'ObjectConstructor' entonces no está apuntando a ES2017. Puede usar esta configuración tsconfig.json:

"compilerOptions": {
    "lib": ["es2017"]
}

O simplemente puedes hacer cualquier reparto:

if ((<any>Object).values(Vehicle).includes('car')) {
    // Do stuff here
}
Xiv
fuente
77
JSONLint está mostrando Property 'values' does not exist on type 'ObjectConstructor'.
BBaysinger
55
@BBaysinger en mecanografiado intente esto en su lugar:(<any>Object).values(Vehicle).includes(Vehicle.car)
Salem Ouerdani
1
Excelente. Esta debería ser la respuesta aceptada. La respuesta aceptada no funcionará si mis claves y valores de enumeración son diferentes
Pratap AK
2
Esto no funciona en mecanografiado. También el trabajo en torno proporcionó descansos en IE
Jerin Joseph
3
Creo que esta no es una respuesta a esta pregunta. Su solución (Object.values(Vehicle).includes(Vehicle.car))siempre será verdadera, pero la pregunta es cómo verificar que un valor dado esté incluido en la enumeración, por ejemplo, (Object.values(Vehicle).includes('car'))debería devolver truepero (Object.values(Vehicle).includes('plane'))debería devolver falso.
tommybernaciak
140

Si está utilizando TypeScript, puede usar una enumeración real . Entonces puedes verificarlo usandoin .

Esto funciona solo si su enumeración está basada en números y no está marcada const:

export enum MESSAGE_TYPE {
    INFO = 1,
    SUCCESS = 2,
    WARNING = 3,
    ERROR = 4,
};

var type = 3;

if (type in MESSAGE_TYPE) {

}

Esto funciona porque cuando compila la enumeración anterior, genera el siguiente objeto:

{
    '1': 'INFO',
    '2': 'SUCCESS',
    '3': 'WARNING',
    '4': 'ERROR',
    INFO: 1,
    SUCCESS: 2,
    WARNING: 3,
    ERROR: 4
}
Saravana
fuente
esto solo funciona con enumeraciones adecuadas, ¿verdad? actualmente se define como tal:export const MESSAGE_TYPE = { ... }
Tim Schoch
Si. Solo con enumeraciones adecuadas.
Saravana
Ok, gracias por la explicación. Comprobaré por qué no estamos usando una enumeración adecuada y veré si podemos cambiarla.
Tim Schoch
Cambiamos MESSAGE_TYPEa una enumeración real como usted sugirió y ahora su solución funciona de maravilla. Gracias @Saravana
Tim Schoch
71
Esto no funciona con las enumeraciones de cadenas porque no están mapeadas inversamente: typescriptlang.org/docs/handbook/release-notes/…
Xiv
19

TypeScript v3.7.3

export enum YourEnum {
   enum1 = 'enum1',
   enum2 = 'enum2',
   enum3 = 'enum3',
}

const status = 'enumnumnum';

if (!(status in YourEnum)) {
     throw new UnprocessableEntityResponse('Invalid enum val');
}
Jayson SA
fuente
3
Esto me gusta más
Ashley Coolman
3
Entonces, este ejemplo solo usa key == value y esa es la razón por la que funciona, ¿verdad? Si clave! = Valor, se verificaría por clave.
Konstantin Pelepelin
14
En realidad, este caso funciona solo por una coincidencia. 'enum1' solo se encontraría porque es el mismo valor que la clave. Pero si las claves difieren de los valores, no funciona.
lukas_o
3
@lukas_o tiene razón en eso. Esta solución parece clara a primera vista, pero definitivamente es propensa a errores.
piotros
14

Hay una solución muy simple y fácil para su pregunta:

var districtId = 210;

if (DistrictsEnum[districtId] != null) {

// Returns 'undefined' if the districtId not exists in the DistrictsEnum 
    model.handlingDistrictId = districtId;
}
Ester Kaufman
fuente
Gracias Ester por tu respuesta. Desde que pasé de la programación al diseño UX a tiempo completo, ya no puedo verificar esto. @crowd, ¡avíseme si la respuesta aceptada sigue siendo el camino a seguir en 2019! Saludos
Tim Schoch
2
@TimSchoch Puedo confirmar que esto funciona muy bien al menos para enumeraciones numéricas. Esta es la solución más elegante en mi humilde opinión.
Patrick P.
@PatrickP. ¿Puedes confirmar que la solución propuesta por Ester también funciona para las enumeraciones de cadenas?
Tim Schoch el
1
@TimSchoch ¡Sí! Funciona para cadenas también. como un diccionario: puede usar cualquier tipo para las teclas del diccionario.
Ester Kaufman
9
Tenga en cuenta que esto NO funciona para las enumeraciones de cadenas si la enumeración utiliza inicializadores de cadenas con valores diferentes a los nombres de los miembros de la enumeración. Vea la respuesta de @ Xiv a continuación: stackoverflow.com/a/47755096/4752920
kcstricks
5
export enum UserLevel {
  Staff = 0,
  Leader,
  Manager,
}

export enum Gender {
  None = "none",
  Male = "male",
  Female = "female",
}

Resultado de diferencia en el registro:

log(Object.keys(Gender))
=>
[ 'None', 'Male', 'Female' ]

log(Object.keys(UserLevel))
=>
[ '0', '1', '2', 'Staff', 'Leader', 'Manager' ]

La solución, necesitamos eliminar la clave como un número.

export class Util {
  static existValueInEnum(type: any, value: any): boolean {
    return Object.keys(type).filter(k => isNaN(Number(k))).filter(k => type[k] === value).length > 0;
  }
}

Uso

// For string value
if (!Util.existValueInEnum(Gender, "XYZ")) {
  //todo
}

//For number value, remember cast to Number using Number(val)
if (!Util.existValueInEnum(UserLevel, 0)) {
  //todo
}
Nhan Cao
fuente
0

Según la respuesta de Ryan Cavanaugh , simplemente puede hacer lo siguiente para verificar si un valor está contenido en una enumeración dada:

if ('value4' in someEnum) {
  // ...
}
A. Maitre
fuente