5

Enum

Enum is a newly added grammar in TypeScript, also called enumeration . It is generally used to manage multiple constants of the same series (that is, variables that cannot be modified) for state judgment.

A common state judgment in the Web is to deal with different response status codes when processing a request:

const handleResponseStatus = (status: number): void => {
  switch (status) {
    case 200: // 请求成功时
      // Do something...
      break;
    case 400: // 请求失败时
      // Do something...
      break;
    default:
      throw (new Error('No have status code!'));
  }
};

But because the response status codes are all pre-defined, there is no dispute. The code is written in this way. It is normal, but if the backend customizes some codes when an error occurs in the server, and tells the frontend what these codes represent, Then the above function may become like this:

const handleWrongStatus = (status: string): void => {
  switch (status) {
    case 'A':
      // Do something...
      break;
    case 'B':
      // Do something...
      break;
    case 'C':
      // Do something...
      break;
    default:
      throw (new Error('No have wrong code!'));
  }
};

If it's this kind of code, let alone someone who just took over, even if you wrote it two weeks ago, I'm afraid you can't remember what they all mean without going through the documentation.

But if you make good use of Enum, you can avoid the above-mentioned situation.

Basic usage

Let's first take a look at how Enum is defined. Its usage is very similar to Object:

enum requestStatusCodes {
  error,
  success,
}

There is no need to add an equal sign between the content and the name, and directly describe which variables the Enum has in the curly brackets. It is more appropriate to say that it is a constant rather than a variable, because the value in Enum cannot be modified, so There is no need to worry that these defined rules will change during the execution of the code, leading to execution errors.

Since Enum is used to define the same series of constants, these constants should all maintain specific values. Yes, for each constant in Enum, you can specify a specific value =

But if it is like the previous requestStatusCodes , there is no error if no specific value is specified error or success , because TypeScript will automatically increment the defined value 0 requestStatusCodes will be the same as the following result:

enum requestStatusCodes {
  error = 0,
  success = 1,
}console.log(requestStatusCodes.error) // 0
console.log(requestStatusCodes.success) // 1

In addition to numbers, it can also be defined as a string:

enum requestWrongCodes {
  missingParameter = 'A',
  wrongParameter = 'B',
  invalidToken = 'C',
}console.log(requestWrongCodes.wrongParameter) // 'B'

Of course, you can also set different types in an enum, but this has no meaning at all:

enum requestStatusCodes {
  error = 0,
  success = 'OK',
}

After understanding how the basic Enum is defined, then let's rewrite the handleResponseStatus and handleWrongStatus in the previous code to make them more semantically clear.

First use Enum to define the status description of the two:

enum requestStatusCodes {
  error = 400,
  success = 200,
}

enum requestWrongCodes {
  missingParameter = 'A',
  wrongParameterType = 'B',
  invalidToken = 'C',
}

Then modify the Switch judgment in handleResponseStatus and handleWrongStatus


const handleResponseStatus = (status: number): void => {
  switch (status) {
    case requestStatusCodes.success:
      // Do something...
      break;
    case requestStatusCodes.error:
      // Do something...
      break;
    default:
      throw (new Error('No have status code!'));
  }
};

const handleWrongStatus = (status: string): void => {
  // 如果觉得 requestWrongCodes.missingParameter 太长了,也可以用以下方式:
  const { missingParameter, wrongParameterType, invalidToken, } = requestWrongCodes;
  switch (status) {
    case missingParameter:
      // Do something...
      break;
    case wrongParameterType:
      // Do something...
      break;
    case invalidToken:
      // Do something...
      break;
    default:
      throw (new Error('No have wrong code!'));
  }
};

The modified code becomes more intuitive, because the status codes are put in Enum for unified management, so they can be represented by constant names. After that, no matter how long it takes, you can clearly know what to do here, even No need to write comments or documentation, because the code is the best documentation.

Making good use of Enum can make the code absolutely indispensable, but don’t be discouraged even if you don’t use TypeScript, because TypeScript will eventually be converted to JavaScript. Let’s see how to implement Enum directly in JavaScript!

Implement Enum with native JavaScript

I said earlier that Enum is very similar to Object. If you study the code after Enum is compiled into javascript, you will find that it is really Object.

After Enum is compiled, it will become an object corresponding to the reverse of Key and Value. This looks very simple. For ease of use, the compilation method of it is written as a function below:

const newEnum = (descriptions) => {
  const result = {};
  Object.keys(descriptions).forEach((description) => {
    result[result[description] = descriptions[description]] = description;
  });
  return result;
};

const responseStatus = newEnum({
  error: 400,
  success: 200,
});

// { '200': 'success', '400': 'error', error: 400, success: 200 }
console.log(responseStatus);

Although the results obtained are the same, the most valuable constant feature in Enum is lost. If you can’t make it unmodifiable, you may inadvertently change it in the code, causing the execution result to be wrong, so you can Finally, use Object.freeze() external operations from adding, deleting or redefining any Property:


const newEnum = (descriptions) => {
  const result = {};
  Object.keys(descriptions).forEach((description) => {
    result[result[description] = descriptions[description]] = description;
  });
  return Object.freeze(result);
};

const responseStatus = newEnum({
  error: 400,
  success: 200,
});

// 即使不小心修改了
responseStatus['200'] = 'aaaaaaaa';

// 仍然是 { '200': 'success', '400': 'error', error: 400, success: 200 }
console.log(responseStatus);

In this way, Enum can be easily implemented in JavaScript.

Usage of const Enum

From the previous JavaScript code, you can see that Enum will become an Object corresponding to Key and Value after being compiled, that is to say, whether you use Key or Value, you can retrieve the corresponding value.

But if const , Object will not be generated after compilation.

Looking directly at the example, suppose I responseState with const , and also handleResponseStatus make a judgment:

enum responseStatus {
  error = 400,
  success = 200,
}

const handleResponseStatus = (status: number): void => {
  switch (status) {
    case responseStatus.success:
      console.log('请求成功!');
      break;
    case responseStatus.error:
      console.log('请求失败!');
      break;
    default:
      throw (new Error('No have status code!'));
  }
};

It seems that everything is normal, but in the compiled JavaScript, you will find that Enum does not generate Object, but directly declares the value in Enum const

Using const declare Enum has several advantages:

  1. Assuming that there are a lot of Enums to be used, IIFE will be used to generate Objects during execution. Binding Key and Value to Objects will cause some efficiency losses and increase memory, but const will not produce Object, there will be no such problems.
  2. const , you need to always find the corresponding value from Object when judging. If Enum is declared with 060c16419ec659, the declared value will be directly put into the judgment when compiling into JS.

But in this way, it is impossible to reverse the value from Enum, because it does not generate an object:

const enum responseStatus {
  error = 400,
  success = 200,
}// 会出错,因为已经没有对象可供查找了
console.log(responseStatus[400])// 但这个不会有问题,因为编译的时候会直接填值
console.log(responseStatus.error)// 编译后:
// console.log(400)

173382ede7319973.gif


This article first published WeChat public account: Front-end Pioneer

Welcome to scan the QR code to follow the official account, and push you fresh front-end technical articles every day

欢迎扫描二维码关注公众号,每天都给你推送新鲜的前端技术文章


Welcome to continue reading other highly praised articles in this column:



疯狂的技术宅
44.4k 声望39.2k 粉丝