TypeScript deep learning enumeration types

I saw a very good sentence today, and I want to share it with you:

Ambition is the door to a career, and work is a journey into the house. – Pasteur

Enums are a new data type added to [TypeScript] , which is common in many other languages, but not in JavaScript. Using enumerations, we can give some hard-to-understand constants a set of meaningful and intuitive names to make it more intuitive. You can understand that an enumeration is a dictionary. Enums are defined using the enum keyword, and TypeScript supports enums for numbers and strings.

1. Numeric enumeration

Let’s start with a simple example of a numeric enumeration to see what an enumeration does:

enum Status { // Here your TSLint may report one: enum declarations can only be merged with namespace or other enum declarations. Such errors, this does not affect compilation, the problem of declaration merging will be discussed in the following subsections.
  Uploading,
  Success,
  Failed
}
console.log(Status.Uploading); // 0
console.log(Status["Success"]); // 1
console.log(Status.Failed); // 2

We use the [enum] keyword to define an enumeration value status, which contains three fields, each of which is separated by a comma. When we use the element value of the enumeration value, just like accessing the property of the object, you can use the ‘.’ operator and the ‘[]’ to access the value inside, just like the object.

Looking at the output result, Status.Uploading is 0, Status[‘Success’] is 1, and Status.Failed is 2. When we defined the enumeration Status, we did not specify the index number because this is the default number, and we also You can specify by yourself:

// Modify the starting number 
enum Color {
  Red = 2,
  Blue,
  Yellow
}console.log (Color.Red, Color.Blue, Color.Yellow); 
// 2 3 4 
// Specify the index value of any field 
enum Status {
  Success = 200,
  NotFound = 404,
  Error = 500
}
console.log ( Status.Success , Status.NotFound , Status.Error); // 200 404 500 
// Specify some fields, others use the default incremental index 
enum Status {
  Ok = 200,
  Created,
  Accepted,
  BadRequest = 400,
  Unauthorized
}
console.log(Status.Created, Status.Accepted, Status.Unauthorized); // 201 202 401

Numeric enumerations can use computed values ​​and constants when defining values. However, it should be noted that if a field uses a calculated value or constant, the field immediately following the field must be set to an initial value. The default incremental value cannot be used here. Let’s see an example:

const  getValue = () => { 
  return  0; 
}; 
enum  ErrorIndex { 
  a = getValue(), 
  b,  // error enum member must have initialized value 
  c 
} 
enum  RightIndex { 
  a = getValue(), 
  b = 1, 
  c 
} 
const  Start = 1; 
enum  Index { 
  a = Start, 
  b,  // error enum member must have initialized value 
  c 
}

2. Reverse mapping

When we define an enumeration value, we can get the corresponding value value in the form of Enum[‘key’] or Enum.key. TypeScript also supports reverse mapping, but reverse mapping only supports numeric enumeration, and the [string] enumeration we will talk about later is not supported. Let’s see an example of reverse mapping:

enum status
  Success = 200,
  NotFound = 404,
  Error = 500
}
console.log(Status["Success"]); // 200
console.log(Status[200]); // 'Success'
console.log(Status[Status["Success"]]); // 'Success'

The enumeration defined in TypeScript is actually an object after compilation. Let’s see what the enumeration value Status in the above example looks like after compilation:

{
    200: "Success",
    404: "NotFound",
    500: "Error",
    Error: 500,
    NotFound: 404,
    Success: 200
}

As you can see, TypeScript will use the field names of the enumeration values ​​we define as the property names and values ​​of the object, respectively, and add the field values ​​of the enumeration values ​​as the value and property names of the object, and add them to the object at the same time. In this way, we can get the value from the field name of the enumeration value, and we can also get the field name from the value of the enumeration value.

3. String enumeration

TypeScript 2.4 adds a new string enumeration. The string enumeration value requires that the value of each field must be a string literal, or another string enumeration member in the enumeration value. Let’s take a look first. Simple example:

enum Message {
  Error = "Sorry, error",
  Success = "Hoho, success"
}
console.log(Message.Error); // 'Sorry, error'

Let’s look at our example of using other enum members in an enum value:

enum Message {
  Error = "error message",
  ServerError = Error,
  ClientError = Error
}
console.log(Message.Error); // 'error message'
console.log(Message.ServerError); // 'error message'

Note that other enumeration members here refer to enumeration members in the same enumeration value, because string enumerations cannot use constants or computed values, so they cannot use members in other enumeration values.

4. Heterogeneous enumeration

In simple terms, heterogeneous enumeration means that the member values ​​in the enumeration value have both numeric and string types, as follows:

enum Result {
  Faild = 0,
  Success = "Success"
}

But if this is not really needed, it is not recommended to use it. Because often when we organize a class of values ​​into an enumeration value, their characteristics are similar. For example, the return status code when we make an interface request, if the status code is a numerical value, if it is a prompt message, it is a string, so when using enumeration, it is often possible to avoid the use of heterogeneous enumeration. It’s a good type of arrangement.

5. Enumeration member types and union enumeration types

If the values ​​of all members in the enumeration value are literal type values, then each member of the enumeration and the enumeration value itself can be used as a type. Let’s first look at the values ​​of the enumeration members that meet the conditions: Which:

  • an enumeration member without an initial value, e.g. enum E{A}
  • The value is a string literal, e.g. enum E {A = ‘a’}
  • The value is a numeric literal, or a numeric literal with a – sign, such as enum E {A = 1}, enum E { A = -1 }

When the values ​​of all members of our enumeration value are the above three cases, the enumeration value and members can be used as types:

(1) Enumeration member type

We can use members of eligible enumeration values ​​as types, see an example:

enum  Animal { 
  Dog = 1, 
  Cat = 2 
} 
interface  Dog { 
  type : Animal.Dog; // Animal.Dog is used here as the type, the specified interface Dog must have a type field, and the type is Animal.Dog 
} 
interface  Cat { 
  type : Animal.Cat; // same here 
} 
let  cat1: Cat = { 
  type : Animal.Dog // error [ts] Cannot assign type 'Animal.Dog' to type 'Animal.Cat' 
}; 
let  dog: Dog = { 
  type : Animal.Dog 
};

(2) Union [enumeration type] Union [enumeration type]

When our enumeration value meets the conditions, the enumeration value can be regarded as a union type containing all members. Let’s look at the example first:

enum  Status { 
  Off, 
  On 
} 
interface  Light { 
  status : Status; 
} 
enum  Animal { 
  Dog = 1, 
  Cat = 2 
} 
const  light1: Light = { 
  status : Animal.Dog // error Cannot assign type 'Animal.Dog' to type "Status" 
}; 
const  light2: Light = { 
  status : Status.Off 
}; 
const  light3: Light = { 
  status : Status.On 
};

The above example defines the type of the status field of the interface Light as the enumeration value Status, then the attribute value of status must be one of Status.Off and Status.On, which is equivalent to status: Status.Off | Status.On.

6. Enumeration at runtime

An enum is actually an object after being compiled into JavaScript. We have mentioned this before. Since it is an object, it can be used as an object. Let’s look at an example:

enum E {
  A,
  B
}
const getIndex = (enumObj: { A: number }): number => {
  return enumObj.A;
};
console.log(getIndex(E)); // 0

The above example requires that the parameter of getIndex is an object, and it must contain an attribute named ‘A’ whose value is a numeric type, as long as there is this attribute. When we call this function, it is okay to pass the enumeration value E as an argument, because it is an object at runtime, including the property ‘A’, because it is equivalent to the following object at runtime:

{
    0: "A",
    1: "B",
    A: 0,
    B: 1
}

7. const enum

After we define the enumeration value, the code compiled into JavaScript creates a corresponding object that we can use when the program runs. But what if we use enums just to make the program readable and don’t need the compiled object? This will increase the amount of compiled code by some. So TypeScript added const enum (fully embedded enumeration) in 1.4, and added the const keyword before the statement that defines the enumeration mentioned earlier, so that the compiled code will not create this object, but will take it from the enumeration To the corresponding value to replace, look at our definition below:

enum status
  Off,
  On
}
const enum Animal {
  Dog,
  Cat
}
const status = Status.On;
const animal = Animal.Dog;

The above example compiles to JavaScript like this:

was Status;
(function(Status) {
  Status[(Status["Off"] = 0)] = "Off";
  Status[(Status["On"] = 1)] = "On";
})(Status || (Status = {}));
var status = Status.On;
var animal = 0; / Dog /

Let’s take a look at the processing of Status. First, define a variable Status, then define an immediate execution function, and add corresponding properties to Status in the function. First, Status[“Off”] = 0 is to set the Off property to the Status object, and the value is set to If it is 0, the return value of this assignment expression is the value to the right of the equal sign, which is 0, so Status[Status[“Off”] = 0] =”Off”is equivalent to Status[0] =”Off”. After creating this object, assign the On property value of Status to status; let’s look at the processing of animal, we see that the compiled code does not create an Animal object like Status, but directly replaces the value of Animal.Dog with 0 To the Animal.Dog position of the const animal = Animal.Dog expression, this is the usage of const enum.

Well, that’s it for today, and we will continue to update TypeScript related content in the future.

Leave a Comment

Your email address will not be published. Required fields are marked *