检查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
Tim Schoch

@TimSchoch您只!!MESSAGE_TYPE[type]需要检查一个值是否存在即可。MESSAGE_TYPE[type]如果的值type不存在,将返回undefinedMESSAGE_TYPE
Kevin Babcock

1
@Kevin Babcock但是,其中一个枚举值映射到会失败0
IngoBürk18年

@IngoBürk太好了!我想可以做一个明确的检查MESSAGE_TYPE[type] !== undefined
凯文·巴布科克

Answers:


212

如果要让它与字符串枚举一起使用,则需要使用,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)
Salem Ouerdani,

1
优秀的。这应该是公认的答案。如果我的枚举键和值不同,则无法接受的答案
Pratap AK,

2
这在打字稿中不起作用。另外,工作的周围设有休息在IE
Jerin约瑟夫

3
我相信这不是这个问题的答案。您的解决方案(Object.values(Vehicle).includes(Vehicle.car))将永远是对的,但问题是如何检查枚举中是否包含给定值,例如(Object.values(Vehicle).includes('car'))应返回true(Object.values(Vehicle).includes('plane'))应返回false。
tommybernaciak

140

如果使用TypeScript,则可以使用实际的enum。然后,您可以使用检查它in

仅当您的枚举基于数字且未标记时,此方法才有效const

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

var type = 3;

if (type in MESSAGE_TYPE) {

}

之所以起作用,是因为当您编译上面的枚举时,它会生成下面的对象:

{
    '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/...
十四

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
我最喜欢这个
Ashley Coolman

3
因此,此示例仅使用key == value,这就是它起作用的原因,对吗?如果key!= value,它将按键检查。
康斯坦丁·佩莱佩林

13
实际上,这种情况仅由于巧合而起作用。只能找到“ 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设计,因此无法再对此进行验证。@crowd,让我知道我接受的答案是否仍然是2019年的方式!欢呼声
蒂姆·肖克

2
@TimSchoch我可以确认,至少对于数字枚举,它可以很好地工作。这是恕我直言的最优雅的解决方案。
Patrick P.19年

@PatrickP。您可以确认Ester提出的解决方案也适用于字符串枚举吗?
蒂姆·肖克

1
@TimSchoch是的!它也适用于字符串。就像字典一样-您可以为字典中的键使用任何类型。
Ester Kaufman

9
请注意,如果枚举使用的字符串初始值设定项的值与枚举成员名称不同,则此方法不适用于字符串枚举。参见下面的
@Xiv

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
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.