如何比较 TypeScript 中的枚举
How to compare Enums in TypeScript
在 TypeScript 中,我想比较两个包含枚举值的变量。这是我的最小代码示例:
enum E {
A,
B
}
let e1: E = E.A
let e2: E = E.B
if (e1 === e2) {
console.log("equal")
}
使用 tsc
(v 2.0.3) 编译时出现以下错误:
TS2365: Operator '===' cannot be applied to types 'E.A' and 'E.B'.
与 ==
、!==
和 !=
相同。
我尝试添加 const
关键字,但似乎没有效果。
TypeScript spec 表示如下:
4.19.3 The <, >, <=, >=, ==, !=, ===, and !== operators
These operators require one or both of the operand types to be assignable to the other. The result is always of the Boolean primitive type.
这(我认为)解释了错误。但是我怎样才能绕过它呢?
旁注
我正在使用带有 atom-typescript 的 Atom 编辑器,但我的编辑器中没有任何 errors/warnings。但是当我在同一目录中 运行 tsc
时,我得到了上面的错误。我以为他们应该使用相同的 tsconfig.json
文件,但显然不是这样。
好吧,我想我找到了一些有用的东西:
if (e1.valueOf() === e2.valueOf()) {
console.log("equal")
}
但我有点惊讶文档中没有提到这一点。
还有另一种方法:如果您不希望生成的 javascript 代码受到任何影响,您可以使用类型转换:
let e1: E = E.A
let e2: E = E.B
if (e1 as E === e2 as E) {
console.log("equal")
}
一般来说,这是由基于控制流的类型推断引起的。使用当前的打字稿实现,只要涉及函数调用,它就会关闭,因此您也可以这样做:
let id = a => a
let e1: E = id(E.A)
let e2: E = id(E.B)
if (e1 === e2) {
console.log('equal');
}
奇怪的是,如果 id
函数被声明为 return 与它的参数完全相同的类型,仍然没有错误:
function id<T>(t: T): T { return t; }
唯一对我有用的(在打字稿 2.2.1 中)是这样的:
if (E[e1] === E[e2]) {
console.log("equal")
}
这会比较表示名称的字符串(例如 "A" 和 "B")。
如果能够用这个比较两个枚举
if (product.ProductType &&
(product.ProductType.toString() == ProductTypes[ProductTypes.Merchandises])) {
// yes this item is of merchandises
}
ProductTypes 是这个 export enum ProductTypes{Merchandises,Goods,...}
原版AUG/18
在我的例子中,上述解决方案 none 有效,原因是我将枚举值转换为枚举对象。
之后我想知道枚举是否等同于另一个枚举对象...所以我创建了以下 generic 函数:
public static enumEquals<T>(e: any, e1: T, e2: T): boolean {
const v1 = this.enumValue(e, e1);
return v1 === this.enumValue(e, e2, typeof v1);
}
private static enumValue<T>(enumType: any, value: T, validType?: string) {
let v = enumType[value];
if (!validType) {
return v;
}
while (typeof v !== validType) {
v = enumType[v];
}
return v;
}
这是我的测试用例示例:
enum SomeEnum {
VALUE1, VALUE2, VALUE3, VALUE_DEF
}
const enumRefKey = localStorage.getItem('someKey');
const parsedEnum = SomeEnum[enumRefKey] || SomeEnum.VALUE_DEF;
console.log(parsedEnum);
if (parsedEnum === SomeEnum.VALUE_DEF) {
// do stuff
}
显然该代码无效,在我尝试了此处针对此问题给出的解决方案后,我发现当 enumRefKey 有效时 console.log(parsedEnum) 正在打印数字,而文本 VALUE_DEF 则不是。使用所有其他解决方案会发生相同的结果:
- 将枚举解析为 SomeEnum
- parsedEnum.valueOf()
- SomeEnum[parsedEnum]
使用通用方法的解决方案如下所示:
enum SomeEnum {
VALUE1, VALUE2, VALUE3, VALUE_DEF
}
const enumRefKey = localStorage.getItem('someKey');
const parsedEnum = SomeEnum[enumRefKey] || SomeEnum.VALUE_DEF;
console.log(parsedEnum);
if (this.enumEquals(SomeEnum, parsedEnum, SomeEnum.VALUE_DEF) {
// do stuff
}
更新SEP/21
避免 TypeScript
比较中与 enums
相关的所有问题的最佳方法是像下面的示例一样声明它们。
而不是这个:
enum SomeEnum {
VALUE1, VALUE2, VALUE3
}
这样做:
enum SomeEnum {
VALUE1 = 'VALUE1', VALUE2 = 'VALUE2', VALUE3 = 'VALUE3'
}
这样,从现在开始,您将不需要将枚举值强制转换或转换为枚举对象,如果您需要,它也将始终有效。使用此解决方案,以下所有示例均有效,它们将 return true
:
console.log(SomeEnum['VALUE1'] === 'VALUE1'); // prints 'true'
console.log(SomeEnum['VALUE1'] === SomeEnum.VALUE1); // prints 'true'
console.log(SomeEnum['VALUE1'] === 'VALUE1' as SomeEnum); // prints 'true'
console.log(SomeEnum['VALUE1'] === 'VALUE1'); // prints 'true'
console.log(SomeEnum['VALUE1'] === (<SomeEnum>'VALUE1')); // prints 'true'
console.log(SomeEnum.VALUE1 === 'VALUE1' as SomeEnum); // prints 'true'
console.log(SomeEnum.VALUE1 === (<SomeEnum>'VALUE1')); // prints 'true'
console.log(SomeEnum.VALUE1 === 'VALUE1'); // prints 'true'
罪魁祸首
所有这些问题的原因是当 TypeScript
被编译为 JavaScript
枚举被解析为 objects
像这样
// this enum at TS
enum SomeEnum {
VALUE1, VALUE2, VALUE3
}
// is parsed to JS like this:
{
VALUE1: 1, VALUE2: 2, VALUE3: 3, 1: 'VALUE1', 2: 'VALUE2', 3: 'VALUE3'
}
如您所见,一旦枚举被解析为 JS,所有比较问题的原因就变得很明显,因为我们可能错误地比较了 string
与 number
,这可能会以 false 结束- 积极的结果。以下是解析为 JS 的第二个枚举,效果更好:
// this enum at TS
enum SomeEnum {
VALUE1 = 'VALUE1', VALUE2 = 'VALUE2', VALUE3 = 'VALUE3'
}
// is parsed to JS like this:
{
'VALUE1': 'VALUE1', 'VALUE2': 'VALUE2', 'VALUE3': 'VALUE3'
}
之所以抛出错误,是因为编译器意识到该语句始终为假,因此是多余的。您声明两个明显不相等的变量,然后尝试查看它们是否相等。
如果您将其更改为例如:
enum E {
A,
B
}
foo() {
let e1: E = E.A
let e2: E
e2 = bar();
if (e1 === e2) {
console.log("equal")
}
}
bar(): E {
return E.B
}
编译应该没有错误。
旁注,某事。喜欢
let e1 = E.A;
if (e1 && e1 === E.B) {
...
}
也不会编译,因为 e1
在这种情况下是 0
(因为 A 是第一个枚举 'option')因此 false
意味着第二个永远不会达到状态(不管第二条语句在这种情况下是否有效)
我会像这样定义 Enum 的值并与 ===
进行比较
const enum AnimalInfo {
Tiger = "Tiger",
Lion = "Lion"
}
let tigerStr = "Tiger";
if (tigerStr === AnimalInfo.Tiger) {
console.log('true');
} else {
console.log('false');
}
在打字稿中的示例枚举:
enum Example {
type1,
type2
};
转化为javascript进入这个对象:
Example {
'0': 'type1', 'type1': 0,
'1': 'type2', 'type2': 1
}
我在打字稿中比较枚举时遇到了很多问题。这个简单的脚本解决了这个问题:
enum Example {
type1 = 'type1',
type2 = 'type2'
};
那么在javascript中,对象转化为:
Example {
'type1': 'type1',
'type2': 'type2'
}
如果您不需要使用枚举 - 最好不要使用。 Typescript 有更高级的类型,更多在这里:
https://www.typescriptlang.org/docs/handbook/advanced-types.html
您可以改用:
type Example = 'type1' | 'type2';
将枚举类型转换为字符串是一项非常有价值的技术。
例如;
if (String(e1) === String(e2)) {
console.log("equal, now actually works!")
}
在 TypeScript 中,我想比较两个包含枚举值的变量。这是我的最小代码示例:
enum E {
A,
B
}
let e1: E = E.A
let e2: E = E.B
if (e1 === e2) {
console.log("equal")
}
使用 tsc
(v 2.0.3) 编译时出现以下错误:
TS2365: Operator '===' cannot be applied to types 'E.A' and 'E.B'.
与 ==
、!==
和 !=
相同。
我尝试添加 const
关键字,但似乎没有效果。
TypeScript spec 表示如下:
4.19.3 The <, >, <=, >=, ==, !=, ===, and !== operators
These operators require one or both of the operand types to be assignable to the other. The result is always of the Boolean primitive type.
这(我认为)解释了错误。但是我怎样才能绕过它呢?
旁注
我正在使用带有 atom-typescript 的 Atom 编辑器,但我的编辑器中没有任何 errors/warnings。但是当我在同一目录中 运行 tsc
时,我得到了上面的错误。我以为他们应该使用相同的 tsconfig.json
文件,但显然不是这样。
好吧,我想我找到了一些有用的东西:
if (e1.valueOf() === e2.valueOf()) {
console.log("equal")
}
但我有点惊讶文档中没有提到这一点。
还有另一种方法:如果您不希望生成的 javascript 代码受到任何影响,您可以使用类型转换:
let e1: E = E.A
let e2: E = E.B
if (e1 as E === e2 as E) {
console.log("equal")
}
一般来说,这是由基于控制流的类型推断引起的。使用当前的打字稿实现,只要涉及函数调用,它就会关闭,因此您也可以这样做:
let id = a => a
let e1: E = id(E.A)
let e2: E = id(E.B)
if (e1 === e2) {
console.log('equal');
}
奇怪的是,如果 id
函数被声明为 return 与它的参数完全相同的类型,仍然没有错误:
function id<T>(t: T): T { return t; }
唯一对我有用的(在打字稿 2.2.1 中)是这样的:
if (E[e1] === E[e2]) {
console.log("equal")
}
这会比较表示名称的字符串(例如 "A" 和 "B")。
如果能够用这个比较两个枚举
if (product.ProductType &&
(product.ProductType.toString() == ProductTypes[ProductTypes.Merchandises])) {
// yes this item is of merchandises
}
ProductTypes 是这个 export enum ProductTypes{Merchandises,Goods,...}
原版AUG/18
在我的例子中,上述解决方案 none 有效,原因是我将枚举值转换为枚举对象。
之后我想知道枚举是否等同于另一个枚举对象...所以我创建了以下 generic 函数:
public static enumEquals<T>(e: any, e1: T, e2: T): boolean {
const v1 = this.enumValue(e, e1);
return v1 === this.enumValue(e, e2, typeof v1);
}
private static enumValue<T>(enumType: any, value: T, validType?: string) {
let v = enumType[value];
if (!validType) {
return v;
}
while (typeof v !== validType) {
v = enumType[v];
}
return v;
}
这是我的测试用例示例:
enum SomeEnum {
VALUE1, VALUE2, VALUE3, VALUE_DEF
}
const enumRefKey = localStorage.getItem('someKey');
const parsedEnum = SomeEnum[enumRefKey] || SomeEnum.VALUE_DEF;
console.log(parsedEnum);
if (parsedEnum === SomeEnum.VALUE_DEF) {
// do stuff
}
显然该代码无效,在我尝试了此处针对此问题给出的解决方案后,我发现当 enumRefKey 有效时 console.log(parsedEnum) 正在打印数字,而文本 VALUE_DEF 则不是。使用所有其他解决方案会发生相同的结果:
- 将枚举解析为 SomeEnum
- parsedEnum.valueOf()
- SomeEnum[parsedEnum]
使用通用方法的解决方案如下所示:
enum SomeEnum {
VALUE1, VALUE2, VALUE3, VALUE_DEF
}
const enumRefKey = localStorage.getItem('someKey');
const parsedEnum = SomeEnum[enumRefKey] || SomeEnum.VALUE_DEF;
console.log(parsedEnum);
if (this.enumEquals(SomeEnum, parsedEnum, SomeEnum.VALUE_DEF) {
// do stuff
}
更新SEP/21
避免 TypeScript
比较中与 enums
相关的所有问题的最佳方法是像下面的示例一样声明它们。
而不是这个:
enum SomeEnum {
VALUE1, VALUE2, VALUE3
}
这样做:
enum SomeEnum {
VALUE1 = 'VALUE1', VALUE2 = 'VALUE2', VALUE3 = 'VALUE3'
}
这样,从现在开始,您将不需要将枚举值强制转换或转换为枚举对象,如果您需要,它也将始终有效。使用此解决方案,以下所有示例均有效,它们将 return true
:
console.log(SomeEnum['VALUE1'] === 'VALUE1'); // prints 'true'
console.log(SomeEnum['VALUE1'] === SomeEnum.VALUE1); // prints 'true'
console.log(SomeEnum['VALUE1'] === 'VALUE1' as SomeEnum); // prints 'true'
console.log(SomeEnum['VALUE1'] === 'VALUE1'); // prints 'true'
console.log(SomeEnum['VALUE1'] === (<SomeEnum>'VALUE1')); // prints 'true'
console.log(SomeEnum.VALUE1 === 'VALUE1' as SomeEnum); // prints 'true'
console.log(SomeEnum.VALUE1 === (<SomeEnum>'VALUE1')); // prints 'true'
console.log(SomeEnum.VALUE1 === 'VALUE1'); // prints 'true'
罪魁祸首
所有这些问题的原因是当 TypeScript
被编译为 JavaScript
枚举被解析为 objects
像这样
// this enum at TS
enum SomeEnum {
VALUE1, VALUE2, VALUE3
}
// is parsed to JS like this:
{
VALUE1: 1, VALUE2: 2, VALUE3: 3, 1: 'VALUE1', 2: 'VALUE2', 3: 'VALUE3'
}
如您所见,一旦枚举被解析为 JS,所有比较问题的原因就变得很明显,因为我们可能错误地比较了 string
与 number
,这可能会以 false 结束- 积极的结果。以下是解析为 JS 的第二个枚举,效果更好:
// this enum at TS
enum SomeEnum {
VALUE1 = 'VALUE1', VALUE2 = 'VALUE2', VALUE3 = 'VALUE3'
}
// is parsed to JS like this:
{
'VALUE1': 'VALUE1', 'VALUE2': 'VALUE2', 'VALUE3': 'VALUE3'
}
之所以抛出错误,是因为编译器意识到该语句始终为假,因此是多余的。您声明两个明显不相等的变量,然后尝试查看它们是否相等。
如果您将其更改为例如:
enum E {
A,
B
}
foo() {
let e1: E = E.A
let e2: E
e2 = bar();
if (e1 === e2) {
console.log("equal")
}
}
bar(): E {
return E.B
}
编译应该没有错误。
旁注,某事。喜欢
let e1 = E.A;
if (e1 && e1 === E.B) {
...
}
也不会编译,因为 e1
在这种情况下是 0
(因为 A 是第一个枚举 'option')因此 false
意味着第二个永远不会达到状态(不管第二条语句在这种情况下是否有效)
我会像这样定义 Enum 的值并与 ===
const enum AnimalInfo {
Tiger = "Tiger",
Lion = "Lion"
}
let tigerStr = "Tiger";
if (tigerStr === AnimalInfo.Tiger) {
console.log('true');
} else {
console.log('false');
}
在打字稿中的示例枚举:
enum Example {
type1,
type2
};
转化为javascript进入这个对象:
Example {
'0': 'type1', 'type1': 0,
'1': 'type2', 'type2': 1
}
我在打字稿中比较枚举时遇到了很多问题。这个简单的脚本解决了这个问题:
enum Example {
type1 = 'type1',
type2 = 'type2'
};
那么在javascript中,对象转化为:
Example {
'type1': 'type1',
'type2': 'type2'
}
如果您不需要使用枚举 - 最好不要使用。 Typescript 有更高级的类型,更多在这里: https://www.typescriptlang.org/docs/handbook/advanced-types.html 您可以改用:
type Example = 'type1' | 'type2';
将枚举类型转换为字符串是一项非常有价值的技术。
例如;
if (String(e1) === String(e2)) {
console.log("equal, now actually works!")
}