Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
883 views
in Technique[技术] by (71.8m points)

typescript - Using enums as types allows values that don't exist in the enum

I have this typescript code (typescript playground):

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;

I don't understand why 15 is an acceptable value in this caase. 15 is not a value of the enum, so shouldn't it throw?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

(update 2021-06-10, this is unchanged by the TS4.3 update for union enums)

This is (maybe surprisingly) intended behavior. Numeric enums in TypeScript are sometimes used for bitwise operations, where the listed values are treated as flags. And, as stated by @RyanCavanaugh in a comment on a reported issue about this:

We don't distinguish between flag and non-flag enums, so a number that is above [or not equal to] any given enum member isn't necessarily invalid. For example

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

So even though 7 is not equal to any one of the listed Flags enum values, you can still get it by performing bitwise operations of the listed values. I'm pretty sure that the compiler doesn't do any restriction other than checking that the value is a number.

In your case, even though none of the Something enumerated values are 15, it doesn't stop you from doing the (useless and dubiously sane) following:

const value: Something = (Something.Email | Something.All) >> 1;

which amounts to the same thing (10 | 20 evaluates to 30, and 30 >> 1 is 15).


Note that this bitwise stuff doesn't apply to string-based enums, so one way to deal with this is to change your numbers to string literals:

const enum Something {
  None = '0',
  Email = '10',
  All = '20'
}
const value: Something = '15'; // error, as desired

and the compiler warns you that '15' is not a valid value for Something.

Hope that helps. Good luck!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...