Controlla se esiste un valore in enum in TypeScript


163

Ricevo un numero type = 3e devo verificare se esiste in questo enum:

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

Il modo migliore che ho trovato è quello di ottenere tutti i valori di Enum come un array e utilizzare indexOf su di esso. Ma il codice risultante non è molto leggibile:

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

C'è un modo più semplice per farlo?


if(Object.values(MESSAGE_TYPE).includes(+type)? Non c'è molto che puoi fare.
Andrew Li,

1
Funziona in ES6 ma non in ES5, sfortunatamente
Tim Schoch,

@TimSchoch Puoi semplicemente !!MESSAGE_TYPE[type]controllare se esiste un valore. MESSAGE_TYPE[type]tornerà indefinito se il valore di typenon esiste suMESSAGE_TYPE
Kevin Babcock,

1
@Kevin Babcock Quello fallirà di una delle mappe dei valori enum 0, però.
Ingo Bürk,

@Ingo Bürk Ottimo punto! Immagino che potrebbe essere fatto un controllo esplicitoMESSAGE_TYPE[type] !== undefined
Kevin Babcock,

Risposte:


213

Se vuoi che funzioni con enumerazioni di stringhe, devi usarle Object.values(ENUM).includes(ENUM.value)perché le enumerazioni di stringhe non sono mappate al contrario, secondo https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html :

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

diventa:

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

Quindi devi solo fare:

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

Se ricevi un errore per Property 'values' does not exist on type 'ObjectConstructor':, allora non stai prendendo di mira ES2017. Puoi usare questa configurazione di tsconfig.json:

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

O puoi semplicemente fare un cast qualsiasi:

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

7
JSONLint sta mostrando Property 'values' does not exist on type 'ObjectConstructor'.
BBaysinger,

5
@BBaysinger in dattiloscritto prova invece:(<any>Object).values(Vehicle).includes(Vehicle.car)
Salem Ouerdani il

1
Eccellente. Questa dovrebbe essere la risposta accettata. La risposta accettata non funzionerà se le mie chiavi enum e valori sono diversi
Pratap AK

2
Questo non funziona in dattiloscritto. Anche il lavoro intorno ha fornito interruzioni in IE
Jerin Joseph,

3
Credo che questa non sia una risposta a questa domanda. La tua soluzione (Object.values(Vehicle).includes(Vehicle.car))sarà sempre vera, ma la domanda è come verificare che un dato valore sia incluso in enum, ad esempio (Object.values(Vehicle).includes('car'))dovrebbe restituire truema (Object.values(Vehicle).includes('plane'))dovrebbe restituire false.
Tommybernaciak,

140

Se stai usando TypeScript, puoi usare un vero enum . Quindi puoi controllarlo usando in.

Funziona solo se il tuo enum è basato sul numero e non contrassegnato const:

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

var type = 3;

if (type in MESSAGE_TYPE) {

}

Questo funziona perché quando si compila l'enum sopra, genera l'oggetto sottostante:

{
    '1': 'INFO',
    '2': 'SUCCESS',
    '3': 'WARNING',
    '4': 'ERROR',
    INFO: 1,
    SUCCESS: 2,
    WARNING: 3,
    ERROR: 4
}

funziona solo con enumerazioni adeguate, giusto? attualmente è definito come tale:export const MESSAGE_TYPE = { ... }
Tim Schoch

Sì. Solo con enumerazioni adeguate.
Saravana,

ok, grazie per la spiegazione. Controllerò perché non stiamo usando un enum corretto e vedremo se possiamo cambiarlo.
Tim Schoch,

Ci siamo trasformati MESSAGE_TYPEin un vero enum come hai suggerito e ora la tua soluzione funziona come un fascino. Grazie @Saravana
Tim Schoch,

71
Questo non funziona con gli enumeratori di stringhe perché non sono mappati al contrario: 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');
}

3
Mi piace di più
Ashley Coolman,

3
Quindi questo esempio sta usando solo il valore chiave == ed è questo il motivo per cui funziona, giusto? Se chiave! = Valore, verificherebbe per chiave.
Konstantin Pelepelin,

14
In realtà questo caso funziona solo a causa di una coincidenza. 'enum1' sarebbe trovato solo perché ha lo stesso valore della chiave. Ma se le chiavi differiscono dai valori non funziona.
lukas_o

3
@lukas_o ha ragione. Questa soluzione sembra chiara a prima vista ma è sicuramente soggetta a bug.
piotros,

14

C'è una soluzione molto semplice e facile alla tua domanda:

var districtId = 210;

if (DistrictsEnum[districtId] != null) {

// Returns 'undefined' if the districtId not exists in the DistrictsEnum 
    model.handlingDistrictId = districtId;
}

Grazie Ester per la tua risposta. Da quando sono passato dalla programmazione a UX Design a tempo pieno, non posso più verificarlo. @crowd, fammi sapere se la risposta accettata è ancora la strada da percorrere nel 2019! Saluti
Tim Schoch,

2
@TimSchoch Posso confermare che funziona molto bene almeno per gli enumerici numerici. Questa è la soluzione più elegante imho.
Patrick P.

@PatrickP. puoi confermare che la soluzione proposta da Ester funziona anche per gli enumeratori di stringhe?
Tim Schoch,

1
@TimSchoch Sì! Funziona anche con le stringhe. come un dizionario: puoi usare qualsiasi tipo di chiave nel dizionario.
Ester Kaufman,

9
Si noti che questo NON funziona per gli enumeratori di stringhe se l'enum utilizza inizializzatori di stringhe con valori diversi rispetto ai nomi dei membri enum. Vedere @ risposta di Xiv qui di seguito: stackoverflow.com/a/47755096/4752920
kcstricks

5
export enum UserLevel {
  Staff = 0,
  Leader,
  Manager,
}

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

Risultato differenza nel registro:

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

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

La soluzione, dobbiamo rimuovere la chiave come numero.

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
}

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.