使用枚举作为类型允许枚举中不存在的值

Nar*_*etz 6 enums typescript

我有这个打字稿代码(打字稿游乐场):

const enum Something {
  None = 0,
  Email = 10,
  All = 20
}

const enum Other{
  Email = 10;
  Value = 15;
}

interface Foo {
  prop: Something
}
const value2: Something = Something.None;

// Why can 15 be assigned if it's not in the enum?
const value: Something = 15;

// This errors:
const otherValue: Something = 'asdf';

const value3: Something = Something.NotExists;

const value4: Something = Other.Value;

const value5: Something = Other.Email;
Run Code Online (Sandbox Code Playgroud)

我不明白为什么在这种情况下 15 是可接受的值。15 不是枚举的值,所以它不应该抛出吗?

jca*_*alz 7

(更新 2021-06-10,联合枚举的 TS4.3 更新没有改变)

这是(也许令人惊讶的)预期行为。TypeScript 中的数字枚举有时用于按位运算,其中列出的值被视为flags。并且,正如@RyanCavanaugh在对有关此问题的报道的评论中所述:

我们不区分标志和非标志枚举,因此高于[或不等于]任何给定枚举成员的数字不一定无效。例如

enum Flags { Neat = 1, Cool = 2, Great = 4 } // like saying Neat | Cool | Great var x: Flags = 7;

因此,即使7不等于任何一个列出的Flags枚举值,您仍然可以通过对列出的值执行按位运算来获取它。我很确定编译器除了检查该值是否为number.

就您而言,即使没有一个Something枚举值15,它也不会阻止您执行以下操作(无用且可疑的理智):

const value: Something = (Something.Email | Something.All) >> 1;
Run Code Online (Sandbox Code Playgroud)

这相当于相同的事情(10 | 20计算结果为30, 和30 >> 1is 15)。


请注意,这种按位操作不适用于基于字符串的枚举,因此解决此问题的一种方法是将数字更改为字符串文字:

const enum Something {
  None = '0',
  Email = '10',
  All = '20'
}
const value: Something = '15'; // error, as desired
Run Code Online (Sandbox Code Playgroud)

并且编译器警告您这'15'不是 的有效值Something

希望有帮助。祝你好运!