TypeScript introduces many features of statically compiled languages, such as class
(now part of JavaScript), interface
, generics
and union types
.
But today there is a type that needs to be discussed, which is enum
.
For many static languages, enumeration is a very common language feature. For example, c, c#, java and swift. Enumerations are a set of constants that you can use in your code.
We use TypeScript to create a new enum
to represent the days of the week:
enum DayOfWeek {
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
};
This enumeration is declared with the keyword enum DayOfWeek
name 060ceee91a443a. Then we define the constants that can be used in the enumeration.
Now we define a method that accepts the parameters of this enumeration type to determine whether the passed in parameters are weekends.
function isItTheWeekend(day: DayOfWeek) {
switch (day) {
case DayOfWeek.Sunday:
case DayOfWeek.Saturday:
return true;
default:
return false;
}
}
Finally, we can use this:
console.log(isItTheWeekend(DayOfWeek.Monday)); // log: false
This is a very useful method for eliminating magic strings in programs.
However, things are far from as simple as we thought. What will the following code call get after TypeScript compilation?
console.log(isItTheWeekend(2)); // is this valid?
You will be surprised to know the result. Such a call conforms to the TypeScript rules, and the compiler will compile smoothly.
What happened?
The above situation may make you think that you have found a TypeScript bug. In fact, TypeScript is designed like this.
We have created a new digital enumeration , and we can see what the compiled result is in TypeScript Playground:
var DayOfWeek;
(function (DayOfWeek) {
DayOfWeek[DayOfWeek["Sunday"] = 0] = "Sunday";
DayOfWeek[DayOfWeek["Monday"] = 1] = "Monday";
DayOfWeek[DayOfWeek["Tuesday"] = 2] = "Tuesday";
DayOfWeek[DayOfWeek["Wednesday"] = 3] = "Wednesday";
DayOfWeek[DayOfWeek["Thursday"] = 4] = "Thursday";
DayOfWeek[DayOfWeek["Friday"] = 5] = "Friday";
DayOfWeek[DayOfWeek["Saturday"] = 6] = "Saturday";
})(DayOfWeek || (DayOfWeek = {}));
The result of the operation is:
In fact, an enum is a JavaScript object.
The properties of this object are generated according to the enumeration constants defined by me, and corresponding numbers are generated according to the defined order (order, Sunday is 0, Saturday is 6). This object also has a number as a key, and the corresponding constant string as an attribute of the value.
Therefore, we can pass in a number to the above method, and the number is mapped to the corresponding enumeration value. Enumeration is both a numeric constant and a string constant.
When to use
If a method receives an enumeration type parameter, but an arbitrary number can be compiled. This result obviously destroys the type safety system built by TypeScript. When can this be used?
Suppose you have a service that returns a JSON string, and you want to model this string, and the corresponding attribute is an enumeration.
What is stored in your database are numbers. Defining a TypeScript enumeration can easily solve this problem:
const day: DayOfWeek = 3;
The displayed type conversion performed during the assignment will convert the number to the corresponding constant of the enumeration. In other words, we use this enumeration in the code to make the code easier to read.
Control enumerated numbers
The numbers corresponding to the members of the enumeration are generated according to the order defined by the enumeration constants. Can we control the value of this number? is allowed.
enum FileState {
Read = 1,
Write = 2
}
It's just an enumeration describing the possible states of a file.
It may be read or write state, we display the definition of the enumeration value. Now it is very clear what kind of value is reasonable , because the display is defined.
Bit value
But there is another situation that is useful, bit value (Bit).
Let's take a look at the FileState
enumeration, and add a new enumeration value ReadWrite
:
enum FileState {
Read = 1,
Write = 2,
ReadWrite = 3
}
Then suppose there is a method that accepts this type of parameter:
const file = await getFile("/path/to/file", FileState.Read | FileState.Write);
We FileState
used on |
operator. In this way, we can use bit operations to obtain a new enumeration value. In this example, it is the value of 3 and ReadWrite
In fact, we can write more clearly:
enum FileState {
Read = 1,
Write = 2,
ReadWrite = Read | Write
}
The ReadWrite
, but is obtained by bit operations.
But be careful when using enumerations like this.
The following enumeration:
enum Foo {
A = 1,
B = 2,
C = 3,
D = 4,
E = 5
}
If you want to get E
(or 5), can you get it by bit arithmetic: Foo.A | Foo.D or Foo.B | Foo.C
?
So if you want to use the enumeration value to do bitwise operations, then it is clear how to get this value.
Control index
Under normal circumstances, each enumeration value will have a default numeric value. If necessary, you can also explicitly assign values to these enumerations. In addition, you can also assign a value to a certain part of the enumeration:
enum DayOfWeek {
Sunday,
Monday,
Tuesday,
Wednesday = 10,
Thursday,
Friday,
Saturday
}
The first few values are assigned according to the position, Sunday to TuesdayDay is 0 to 2. After that, a new value is given in Wednesday, and each value is incremented by 1. This may cause problems:
enum DayOfWeek {
Sunday,
Monday,
Tuesday,
Wednesday = 10,
Thursday = 2,
Friday,
Saturday
}
Tuesday is assigned a value of 2. What does the generated JavaScript look like?
var DayOfWeek;
(function (DayOfWeek) {
DayOfWeek[DayOfWeek["Sunday"] = 0] = "Sunday";
DayOfWeek[DayOfWeek["Monday"] = 1] = "Monday";
DayOfWeek[DayOfWeek["Tuesday"] = 2] = "Tuesday";
DayOfWeek[DayOfWeek["Wednesday"] = 10] = "Wednesday";
DayOfWeek[DayOfWeek["Thursday"] = 2] = "Thursday";
DayOfWeek[DayOfWeek["Friday"] = 3] = "Friday";
DayOfWeek[DayOfWeek["Saturday"] = 4] = "Saturday";
})(DayOfWeek || (DayOfWeek = {}));
It seems that both Tuesday and Thursday have a value of 2.
Therefore, the set value needs to be displayed.
Non-numeric enumeration
So far, we have only discussed numerical enumerations, but the values of enumerations are not necessarily numbers. It can also be any constant or calculated value:
enum DayOfWeek {
Sunday = "Sun",
Monday = "Mon",
Tuesday = "Tues",
Wednesday = "Wed",
Thursday = "Thurs",
Friday = "Fri",
Saturday = "Sat"
}
Now it is not isItTheWeekend
digital parameters to the 060ceee91a49fb method. This enumeration is no longer a numeric enumeration. However, we can't pass any string in either, because the enumeration knows what kind of value is reasonable.
This also brings another problem:
const day: DayOfWeek = "Mon";
This will not work.
Strings cannot directly assign values to enumerations, but require an explicit type conversion:
const day = "Mon" as DayOfWeek;
Can you assign other values to it? In fact, enumerations can have many types of values:
enum Confusing {
A,
B = 1,
C = 1 << 8,
D = 1 + 2,
E = "Hello World".length
}
The enumeration values in this example are all numbers. However, these numeric values can be assigned directly, or they can be calculated values, or the length
attribute of the string. If they are all constants, they can be multiple types of values:
enum MoreConfusion {
A,
B = 2,
C = "C"
}
In this case, it is difficult for people to understand how the data behind the enumeration works. Therefore, it is best not to use such enumerations.
in conclusion
TypeScript enumerations are a good complement to JavaScript, and they are very useful when used properly. It will help clean up the strings and numbers of magic values in the code. And it is type safe.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。