As far as JS is concerned, enumerations are not a pure type; they invade the JS runtime.

Digital Numeric enums

The default name is 1 and age is 2. Use when it is time to read directly.

Enum Num {name, age} // name is 0 const name = NumCopy the code

You can also specify any number

enum Num {
    name = 0,
    age = 3
}
Copy the code

Since the increase

Numeric enumeration type that is incremented by 1 whenever the value of the first property is specified.

enum Num{
    first = 10,
    second
}
Copy the code

The value is String enums

During debugging, the Number enums are only simple numbers and therefore have no semantics. Strings have semantics.

enum Str {
    up = "UP",
    down = "DOWN"
}
Copy the code

Heterogeneous enumeration Heterogeneous enums

It’s best not to write it this way.

enum BooleanLikeHeterogeneousEnum {  No = 0,  Yes = "YES",}
Copy the code

Computes with constant members Computed and constant members

If the expression of an enumerator is a subtype of a TS expression, its value can be fully evaluated at TS compilation time.

Recommended enumerator expressions are as follows:

1. Literal members: numbers or strings

2. References to constant members can come from other enumeration types

3. Bracketed enumerator expressions

4. Expressions containing one of the unary operators +, -, ~

5. 2 hospital operator, +, -, *, /, %, < <, > >, > > >, &, |, ^

6. Error when using NaN or Infinity

Enum FileAccess {/ / constant None, Read = 1 < < 1, the Write = 1 < < 2, ReadWrite = Read | Write, / / calculated value G = 123 length}Copy the code

Associative enumerations with enumerator types

Literal enumerators are not computable.

When a literal enumerator has no initial value, or its initial value is a string, or a number, or a numeric literal with a unary operator, the member is considered a constant enumerator.

Edge cases

An error occurs when an enumerator is used in both a type and a value.

enum ShapeKind {
    Circle,
    Square
}

interface Circle {
    kind: ShapeKind.Circle;
    radius: number
}

interface Square {
    kind: ShapeKind.Square;
    sideLength: number
}

// crash
let c:Circle = {
    // Type 'ShapeKind.Square' is not assignable to type 'ShapeKind.Circle'.
    kind: ShapeKind.Square,
    radius: 100
}
Copy the code

An enumeration type becomes a collection of each enumeration member. So the type system knows every value in an enumerated type. The result is an error message when comparing values of enumerated types.

enum E { Foo, Bar } function f(x: E){ if(x ! == E.Foo || x ! == E.Bar){ // This condition will always return 'true' since the types 'E.Foo' and 'E.Bar' have no overlap. } }Copy the code

Enumeration types at run time

In the JS runtime, enumerations are real objects.

Enumeration types at compile time

You can use keyof Typeof to get all keys in an enumeration type

enum LogLevel{
    ERROR,
    WARN,
    INFO,
    DEBUG
}

// 'ERROR' | 'WARN' | 'INFO' | 'DEBUG'
type LogLevelStrings = keyof typeof LogLevel
Copy the code

Reverse mappings

Numeric enumerators need to create reverse mapping, which is a mapping of enumeration values –> keys.

enum Enum{
    A
}

let a = Enum.A
// A
let nameOfA = Enum[a]
Copy the code

Compiled into JS

'use strict' var Enum; (function (Enum) {/ / here made A value (0) -- - > the key mapping Enum [Enum [" A "] = 0] = "A"}) (Enum | | (Enum = {})) let A = Enum. Let A nameOfA = Enum[a]Copy the code

This operation is not required for string members.

Enum enum {A = "string"} let nameOfA = enum [A]Copy the code

Compiled into JS

var Enum
(function (Enum){
    Enum["A"] = "string";
})(Enum || (Enum = {}))
var a = Enum.A
var nameOfA = Enum[a]
Copy the code

const enums

By using const, you avoid unnecessary calls that generate extra code and values that are unnecessary.

const enum Enum{
    A = 1,
    B = A * 2
}
Copy the code

Const emuns can only use constant enumeration expressions. Enumeration-related code can be removed completely after compilation.

const enum Direction { Up, Down, Left, Right,}let directions = [ Direction.Up, Direction.Down, Direction.Left, Direction.Right,]; /** @format */var Direction; (function (Direction) { Direction[Direction["Up"] = 0] = "Up"; Direction[Direction["Down"] = 1] = "Down"; Direction[Direction["Left"] = 2] = "Left"; Direction[Direction["Right"] = 3] = "Right"; })(Direction || (Direction = {})); var directions = [ 0 /* Up */, 1 /* Down */, 2 /* Left */, 3 /* Right */,]; //# sourceMappingURL=index.js.mapCopy the code

Of course, this effect cannot be achieved with calculated members.

Right in the bottom

/** @format */enum Enum{ A}const enum Direction { Up, Down, Left = Enum.A, Right = "123".length,}let directions = [ Direction.Up, Direction.Down, Direction.Left, Direction.Right,]; /** @format */var Enum; (function (Enum) { Enum[Enum["A"] = 0] = "A"; })(Enum || (Enum = {})); var Direction; (function (Direction) { Direction[Direction["Up"] = 0] = "Up"; Direction[Direction["Down"] = 1] = "Down"; Direction[Direction["Left"] = 0] = "Left"; Direction[Direction["Right"] = "123".length] = "Right"; })(Direction || (Direction = {})); var directions = [ 0 /* Up */, 1 /* Down */, 0 /* Left */, Direction.Right,]; //# sourceMappingURL=index.js.mapCopy the code

Ambient enums

Declares an enumeration that can be used to describe the shape of an existing enumeration.

delcare enum Enum{
    A = 1,
    B,
    C = 2
}
Copy the code

The difference between non-ambient and ambient enumerations is that an ordinary enumerator with no initial value is constant if the value of its previous enumerator is constant. An ambient with no initial value, an inordinate number of enumerators with no initial value, is always considered a calculated value.

That is, it does not get killed like const enums.

declare enum

declare enum Gender {   Female,   Male}console.log(Gender.Female)
Copy the code

The generated JS

The runtime reported an error because the Gender variable was not present, cheating TS

console.log(Gender.Female); //# sourceMappingURL=index.js.mapCopy the code

declare const enum

declare const  enum Gender {   Female,   Male}console.log(Gender.Female)
Copy the code

The generated JS

console.log(0 /* Female */); //# sourceMappingURL=index.js.mapCopy the code

Objects and enumerations

Objects inferred to be const can be used instead of enumerations

const enum EDirection { Up, Down } const ODirection = { Up: 0, Down: 1 } as const // (enum member) EDirection.Up = 0 EDirection.Up // (property) Up: 0 odirection. Up // function walk(dir: Typeof ODirection = typeof ODirection[keyof typeof ODirection] function run(dir: typeof ODirection){} Direction){} walk(EDirection.Left) run(ODirection.Right)Copy the code

Advantages of enumerations

keep codebase aligned with state of JavaScript and when/if enums are added to JavaScript then you can move to the additional syntax

reference

www.typescriptlang.org/docs/handbo…

zhuanlan.zhihu.com/p/125889229