Перевірте, чи існує значення в перерахунку в TypeScript


163

Я отримую номер type = 3і мушу перевірити, чи існує він у цьому переліку:

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

Найкращий спосіб, який я знайшов, - це отримати всі значення Enum як масив та використовувати indexOf на ньому. Але отриманий код не дуже розбірливий:

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

Чи є простіший спосіб зробити це?


if(Object.values(MESSAGE_TYPE).includes(+type)? Зробити не так вже й багато.
Ендрю Лі

1
Це працює в ES6, але не в ES5, на жаль,
Тім

@TimSchoch Ви можете просто !!MESSAGE_TYPE[type]перевірити, чи існує значення. MESSAGE_TYPE[type]повернеться невизначеним, якщо значення typeне існує наMESSAGE_TYPE
Кевін Бабкок,

1
@Kevin Babcock Однак це не вдасться до однієї зі значень перерахувань перерахунків 0.
Інго Бюрк

@Ingo Bürk Чудова точка! Я здогадуюсь, явна перевірка могла бути зробленаMESSAGE_TYPE[type] !== undefined
Кевін Бабкок

Відповіді:


213

Якщо ви хочете, щоб це працювало із рядковими перерахунками, вам потрібно використовувати, Object.values(ENUM).includes(ENUM.value)оскільки рядкові перерахунки не відображаються в зворотному порядку, відповідно до https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html :

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

стає:

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

Тож вам просто потрібно зробити:

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

Якщо ви отримаєте помилку для:, Property 'values' does not exist on type 'ObjectConstructor'ви не орієнтуєтесь на ES2017. Ви можете використовувати цей конфігурацію tsconfig.json:

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

Або ви можете просто зробити будь-яку ролю:

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

7
JSONLint показує Property 'values' does not exist on type 'ObjectConstructor'.
BBaysinger

5
@BBaysinger в машинописі спробуйте це замість цього:(<any>Object).values(Vehicle).includes(Vehicle.car)
Салем Оуердані

1
Відмінно. Це має бути прийнятою відповіддю. Прийнята відповідь не буде працювати, якщо ключі та значення моїх перерахунків відрізняються
Pratap AK

2
Це не працює в машинописі. Також робота навколо забезпечила перерви в IE
Jerin Joseph

3
Я вважаю, що це не відповідь на це питання. Ваше рішення (Object.values(Vehicle).includes(Vehicle.car))завжди буде вірним, але питання полягає в тому, як перевірити, чи вказане значення включене в enum, наприклад, (Object.values(Vehicle).includes('car'))повинно повертатися, trueале (Object.values(Vehicle).includes('plane'))повинно повертати помилкове.
tommybernaciak

140

Якщо ви використовуєте TypeScript, ви можете використовувати фактичну перерахунок . Потім ви можете перевірити це за допомогою in.

Це працює лише в тому випадку, якщо ваші перерахунки на основі цифр і не позначені const:

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

var type = 3;

if (type in MESSAGE_TYPE) {

}

Це працює, тому що при складанні вищевказаного enum він генерує об'єкт нижче:

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

це працює лише з належними перерахунками, правда? на даний момент він визначений як такий:export const MESSAGE_TYPE = { ... }
Тім Шоч

Так. Тільки з належними перерахунками.
Саравана

ок, дякую за пояснення. Я перевірю, чому ми не використовуємо належну кількість перерахунків, і побачу, чи можемо ми це змінити.
Тім Шох

Ми змінили MESSAGE_TYPEфактичний перелік, як ви запропонували, і тепер ваше рішення працює як шарм. Спасибі @Saravana
Tim Schoch

71
Це не працює із строковими перерахувань , так як вони не відображаються зворотне: typescriptlang.org/docs/handbook/release-notes / ...
Xiv

20

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
Мені це найбільше подобається
Ешлі Coolman

3
Тож цей приклад просто використовує значення key ==, і саме тому він працює, правда? Якщо ключ! = Значення, воно перевірятиметься ключем.
Костянтин Пелепелін

14
Насправді ця справа працює лише через збіг. "enum1" знайдеться лише тому, що це те саме значення, що і ключ. Але якщо ключі відрізняються від значень, це не працює.
lukas_o

3
@lukas_o вірно з цього приводу. Це рішення на перший погляд виглядає зрозумілим, але воно, безумовно, схильне до помилок.
piotros

14

Є дуже просте і просте рішення вашого питання:

var districtId = 210;

if (DistrictsEnum[districtId] != null) {

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

Дякую Естер за вашу відповідь. Оскільки я перейшов від програмування до штатного UX Design, я більше не можу це перевірити. @crowd, дайте мені знати, якщо я прийняла відповідь, все-таки шлях до 2019 року! Ура
Тім

2
@TimSchoch Я можу підтвердити, що це працює дуже добре принаймні для числових перерахунків. Це найелегантніше рішення imho.
Патрік П.

@PatrickP. чи можете ви підтвердити, що рішення, запропоноване Ester, працює і для рядкових перерахунків?
Тім

1
@TimSchoch Так! Він також працює для рядків. як словник - ви можете використовувати будь-який тип для клавіш у словнику.
Естер Кауфман

9
Зауважте, що це НЕ працює для рядкових перерахунків, якщо enum використовує ініціалізатори рядків з іншими значеннями, ніж імена членів enum. Див @ відповідь Xiv в поле нижче: stackoverflow.com/a/47755096/4752920
kcstricks

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

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

Результат різниці в журналі:

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

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

Рішення, нам потрібно видалити ключ як число.

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;
  }
}

Використання

// 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
}

0

Відповідно до відповіді Райана Кавано , ви можете просто зробити наступне, щоб перевірити, чи міститься значення в заданому перерахунку:

if ('value4' in someEnum) {
  // ...
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.