TypeScript Super Practical Manual for Enumeration of Magic Hall

  • 2021-09-11 19:17:05
  • OfStack

Preface

Maybe the front-end students will ask JavaScript that there is no enumeration type since its birth. Aren't we all living well? Why does TypeScript need to introduce enumerated types?

Maybe the backend students who are forced to write the front end will ask, is the enumeration type of TypeScript the same as that of Java/. NET?
Let's discuss and try to solve it.

Enumeration is required for front end 1 straight

I can assure you that the front-end students will tell you with great certainty that we have never written enumerations. That's because although ECMAScript has enum as a reserved word, no implementation specification for enumerations has been proposed until ES 2020. Language does not provide specifications and language implementation, which does not mean that programmers who are active in thinking and brave in building wheels will not make one by themselves.
If the language doesn't provide it, and we are determined to make one by ourselves, what problems can enumeration solve?

Enumeration is really useful

First, enumeration literally means traversing all members of a finite set of values with several values. The core has two points:

Finite set; Traversal.

That is to say, as long as we need to indicate that the value of a variable must be a member of a finite set, we can't avoid enumeration.

Write an enumeration of JavaScript version

The following is an enumeration implementation that just meets most business requirements:


class Color {
 // tricky Self-increasing enumeration member value 
 static counter = null
 
 //  Enumeration members 
 static Red = new Color('Red')
 static Green = new Color('Green')
 
 //  Reverse mapping 
 static valueOf(value) {
 for (var name in Color) {
  if (!(name in Color.prototype) && Color[name].value === value) {
  return Color[name]
  }
 }
 }
    
 constructor(name, value){
        if ('counter' in Color);else return

 this.name = name
 if (value == null) {
  if (Color.counter === null) {
  this.value = Color.counter = 0
  }
  else {
  this.value = ++Color.counter
  }
 }
 else {
  this.value = Color.counter = value
 }
 }
 
 toString() {
 return `Color.${this.name}`
 }
}
delete Color.counter
Object.freeze(Color) // tricky : Prohibits modifying enumeration members in locations other than definitions 

In fact, we just want to express that some variables will take the finite set of Color containing Red and Green as the value range, but we have to write so many semantically independent codes (strictly follow the principle of "you can write hi and never write hello"). Moreover, in a project of 1 scale, there are often more than 1 enumeration type. Copy and paste can really solve the problem, but it is really not elegant.

The language implementation of TypeScript built-in enumeration can just solve this problem.

The enumeration of TypeScript is different from that of the back end

Back-end students are no strangers to enumeration (unless they are Pyton/Nodejs back-end students). Although TypeScript is a superset of JavaScript, it needs to be compiled into JavaScript code in the end, and it is compatible with the existing JavaScript library, so it is really impossible to be identical to the back-end enumeration type.
Therefore, I still suggest that you use empty cup psychology, re-understand the enumeration types of TypeScript, and use past knowledge as combustion improver instead of fence.

Numeric enumeration types and string enumeration types

TypeScript official website tutorial has explained enumeration types in detail. I think the core is to understand clearly that they are divided into two categories:

Numeric enumeration type


enum Response {
  No = 0, //  Set initializer manually 
  Yes = //  Attach the default initializer that supports automatic growth, so Yes The value of is 1
}

The characteristics are:
1.1. Enumeration members come with default initializers;
1.2. Initializer supports automatic growth;
1.3. Support reverse mapping. (Note: This is a reverse mapping, not a value conversion to an enumeration member.)

String enumeration type


enum Color {
 Red = 'Red',
 Green = 'Green',
}

The characteristics are:
1.1. Initializers must be set for enumeration members;
1.2. The initializer does not support automatic growth;
1.3. Reverse mapping is not supported.

Computation and constant members are actually the subdivision characteristics of initializers in the above two enumeration types.

enum makes reverse mapping of numeric enumeration types possible

Numeric enumeration types described in the previous section support reverse mapping, but only if they are defined by enum. That's because enum Respose {No, Yes,} will eventually be compiled into the following JavaScript code:


var Response;
(function (Response) {
  Response[Response["No"] = 0] = "No";
  Response[Response["Yes"] = 1] = "Yes";
})(Response || (Response = {}));

Then we can get "No" by reverse mapping Response [0].
But not for string enumeration types, look at the compiled code for enum Color {Red= 'Red', Green= 'Green',}


var Color;
(function (Color) {
  Color["Red"] = "Red";
  Color["Green"] = "Green";
})(Color || (Color = {}));

It can only be said that it is very unpretentious, so there is nothing to say. It is good for everyone to pay attention to the differences when using it.

const enum Efficient Inline at Compile Time

The official document clearly states that "in most cases, enumeration is a 10-point effective solution. However, in some cases, the requirements are very strict. In order to avoid the overhead of extra generated code and extra indirect access to enumeration members, we can use const enumeration." Why?
That's because the compile-time enumeration type defined by const enum has no substantial difference from the constant defined by C/C + + # define. To put it bluntly, if only the enumeration type is defined through const enum and there is no other call, this code will be erased directly at compile time.
When the enumerated type is called elsewhere, the values of the members of the enumerated type are directly inlined to the user, as follows:


const enum Response {
  No,
  Yes,
}

console.log(Response.NO, Response.Yes)

When compiled, it becomes console. log (0, 1), and the running effect can only be better than that defined by enum.

When to use enum? In what scenario do you use const enum?

Let's talk about the conclusion first:

Scenarios using enum:
1.1. When reverse mapping is needed;
1.2. When the compiled JavaScript code is required to retain the object. Attribute or object [attribute] form.

Scenarios using const enum: You can use const enum when you don't use enum (haha! )
Rule 1 in the scenario using enum is easy to understand, but what about Rule 2? I have a real-life example here, which can make everyone better understand:
Background: Write type declarations for ExtendScript of Photoshop.
Requirements: The return value of DialogModes. NO in ExtendScript is DialogModes. No itself, and the code form of DialogModes. NO must be retained in the compiled JavaScript.

Then why encourage people to use const enum when they can use const enum?
This is the compile-time optimization method specially prepared by TypeScript for everyone. Why not use good things? Isn't compile-time optimization fragrant?

What does the external enumeration declare enum do?

External enumeration, even if we are forced to write enumeration type declarations for some libraries that have been written in JavaScript in order to make better use of them in the TypeScript development environment.
For example, ExtendScript standard inventory is enumerated in DialogModes. NO, DialogModes. YES, DialogModes. ALL. You then write the following external enumeration type declaration in the. d. ts file


declare enum DialogModes {
  NO,
  YES,
  ALL,
}

Summarize

For enumeration types that we can't get around in daily development, TypeScript provides us with language implementation and compile-time optimization, which not only protects our thinning hair caused by thinking about how to optimize enumeration types, but also greatly reduces the risk of code base volume increase caused by copy and paste.


Related articles: