检查TypeScript中枚举中是否存在值

Tim*_*och 104 javascript enums typescript

我收到一个号码type = 3,必须检查它是否存在于此枚举中:

export const MESSAGE_TYPE = {
    INFO: 1,
    SUCCESS: 2,
    WARNING: 3,
    ERROR: 4,
};
Run Code Online (Sandbox Code Playgroud)

我发现的最好方法是将所有枚举值作为数组并使用indexOf.但结果代码不是很清晰:

if( -1 < _.values( MESSAGE_TYPE ).indexOf( _.toInteger( type ) ) ) {
    // do stuff ...
}
Run Code Online (Sandbox Code Playgroud)

有更简单的方法吗?

Xiv*_*Xiv 126

如果你想使用字符串枚举,你需要使用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'
}
Run Code Online (Sandbox Code Playgroud)

变为:

{
    Car: 'car',
    Bike: 'bike',
    Truck: 'truck'
}
Run Code Online (Sandbox Code Playgroud)

所以你只需要这样做:

if (Object.values(Vehicle).includes(Vehicle.car)) {
    // Do stuff here
}
Run Code Online (Sandbox Code Playgroud)

如果您收到错误:Property 'values' does not exist on type 'ObjectConstructor',那么您的目标不是ES2017.您可以使用此tsconfig.json配置:

"compilerOptions": {
    "lib": ["es2017"]
}
Run Code Online (Sandbox Code Playgroud)

或者你可以做任何演员:

if ((<any>Object).values(Vehicle).includes(Vehicle.car)) {
    // Do stuff here
}
Run Code Online (Sandbox Code Playgroud)

  • `Object.values(Vehicle).includes('car')` 但是警告 `'string' 类型的参数不能分配给'Vehicle' 类型的参数`,所以你还必须输入 assert (37认同)
  • `Object.values&lt;string&gt;(Enum).includes(value)` 对我有用 (11认同)
  • JSONLint显示"PropertyConstructor"类型中不存在"Property"值. (6认同)
  • 打字稿中的@BBaysinger试着改为:`(<any> Object).values(Vehicle).includes(Vehicle.car)` (5认同)
  • 这在打字稿中不起作用。此外,解决方法在 IE 中提供了中断 (4认同)
  • 这个答案已经过时了。TS 4.5 给出“TS2475:‘const’枚举只能在属性或索引访问表达式或导入声明或导出赋值或类型查询的右侧使用。” (4认同)
  • 为我工作,但我必须使用`Object.values(Vehicle).includes('car' as Vehicle)` (4认同)
  • 我相信这不是这个问题的答案。您的解决方案“(Object.values(Vehicle).includes(Vehicle.car))”将始终为真,但问题是如何检查给定值是否包含在枚举中,例如“(Object.values(Vehicle)”。 include('car'))` 应返回 `true` 但 `(Object.values(Vehicle).includes('plane'))` 应返回 false。 (3认同)
  • @Aravin 的解决方案有效并解决了@JHH 提到的错误 (3认同)
  • `错误 TS2345:“get”类型的参数不可分配给“Method”类型的参数。9 console.log(Object.values(Method).includes('get'));` (2认同)
  • 这样可以吗?if (Object.values(Vehicle).includes('car' as any)) { // 在这里做一些事情 } (2认同)

Sar*_*ana 113

如果您使用的是TypeScript,则可以使用实际的枚举.然后你可以使用它来检查它in.请注意,这仅适用于您的枚举不是const且基于数字的情况:

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

var type = 3;

if (type in MESSAGE_TYPE) {

}
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为当您编译上面的枚举时,它会生成以下对象:

{
    '1': 'INFO',
    '2': 'SUCCESS',
    '3': 'WARNING',
    '4': 'ERROR',
    INFO: 1,
    SUCCESS: 2,
    WARNING: 3,
    ERROR: 4
}
Run Code Online (Sandbox Code Playgroud)

  • 这不适用于字符串枚举,因为它们不是反向映射的:https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html (53认同)
  • 是的。仅适用于适当的枚举。 (2认同)
  • 看来这种方法在 2021 年适用于字符串枚举。 (2认同)
  • 对于字符串枚举,它仅在枚举键与值相同时才有效,例如 enum Enum { foo = 'foo' }; 但我不建议在这种情况下依赖它 (2认同)

Soo*_*ead 35

根据 Sandersn 的说法,最好的方法是:

Object.values(MESSAGE_TYPE).includes(type as MESSAGE_TYPE)
Run Code Online (Sandbox Code Playgroud)

  • 这可能是最好、最安全的答案。它避免使用“any”。如果您可以保证枚举的键和值相同,那么“MESSAGE_TYPE 中的类型”语法可能会更好,因为它是键查找而不是值查找。 (3认同)
  • 啊哈!在答案中找到了方法,我可以确认这个解决方案可以正常工作,没有任何“any”或类型抱怨,并且当枚举名称本身与它们各自的实际值不匹配时它可以工作(正如本页上的许多黑客解决方案建议或使用的那样)。应该是公认的答案,尤其是最初来自 TypeScript 的 GitHub。 (3认同)
  • 这适用于您需要检查的每种情况。完美的答案。 (2认同)

Jay*_*tin 29

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

const status = 'enumnumnum';

if (!Object.values(YourEnum).includes(status)) {
     throw new UnprocessableEntityResponse('Invalid enum val');
}
Run Code Online (Sandbox Code Playgroud)

  • 事实上,这个案例的成功只是因为巧合。只能找到“enum1”,因为它与键的值相同。但如果键与值不同,则不起作用。 (41认同)
  • @lukas_o 对此是正确的。这个解决方案乍一看很清晰,但肯定容易出现错误。 (7认同)
  • 我最喜欢这个 (3认同)
  • 所以这个例子只是使用 key==value 这就是它起作用的原因,对吗?如果key!=value,则通过key进行检查。 (3认同)

小智 13

您的问题有一个非常简单的解决方案:

var districtId = 210;

if (DistrictsEnum[districtId] != null) {

// Returns 'undefined' if the districtId not exists in the DistrictsEnum 
    model.handlingDistrictId = districtId;
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,如果枚举使用的字符串初始值设定项的值与枚举成员名称不同,则此方法不适用于字符串枚举。参见下面的@Xiv答案:/sf/answers/3342856751/ (5认同)
  • @TimSchoch我可以确认,至少对于数字枚举,它可以很好地工作。这是恕我直言的最优雅的解决方案。 (2认同)

Nha*_*Cao 8

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

export enum Gender {
  None = "none",
  Male = "male",
  Female = "female",
}
Run Code Online (Sandbox Code Playgroud)

日志中的差异结果:

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

log(Object.keys(UserLevel))
=>
[ '0', '1', '2', 'Staff', 'Leader', 'Manager' ]
Run Code Online (Sandbox Code Playgroud)

解决方案,我们需要将键作为数字删除。

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;
  }
}
Run Code Online (Sandbox Code Playgroud)

用法

// 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
}
Run Code Online (Sandbox Code Playgroud)


小智 7

类型断言是不可避免的。跟进

enum Vehicle {
    Car = 'car',
    Bike = 'bike',
    Truck = 'truck'
}
Run Code Online (Sandbox Code Playgroud)

我找到了一个没有提到的替代方案,所以我想我会分享我的修复方法:

const someString: Vehicle | string = 'car';
const inEnum = (Object.values(Vehicle) as string[]).includes(someString);
Run Code Online (Sandbox Code Playgroud)

我觉得这更真实,因为我们通常使用类型安全(带有字符串)并希望将其与枚举进行比较;将其类型转换为any(原因:永远不要这样做)或Vehicle(原因:可能不真实)有点鲁莽。相反,将Object.values()输出类型转换为字符串数组实际上非常真实。

  • 我认为这一篇是最具可读性的。这就是我最终使用的。 (2认同)
  • 这应该标记为答案。同意@jcollum,这是最易读和最真实的 (2认同)