99

Concurrent visitors over the last 30 minutes. (~)

Peak concurrent visitors -
Yesterday: 0 / Today: 0

TypeScript Enum Types in Depth

TypeScript Enum Types in Depth

# Overview

An enum is both a type and data, and it gives each member a number or string value.
When the range of values is fixed, it is a good choice instead of object or array data.

[enumerate]: to list several examples or facts one by one

TS
1
2
3
4
5
6
7
enum Name { Member1 = Value1, Member2 = Value2 } const member: Name = Name.Member1 // Value1 const value: Name = Value1

# Numbers

Numbers are the most common values for the members of an enum type.
Numbers support bidirectional mapping in enums, and you can assign values explicitly or implicitly.

# Explicit assignment

You can explicitly assign a value to each member of an enum type with the = (assignment) operator.
In the following example, the Week enum type has 7 members from Sun to Sat, and the numbers 0 to 6 are explicitly assigned.

TS
1
2
3
4
5
6
7
8
9
enum Week { Sun = 0, Mon = 1, Tue = 2, Wed = 3, Thu = 4, Fri = 5, Sat = 6 }

You can access an enum's values by member name, like the dot notation of object data, or access (index) them by member name or number, like the bracket notation of arrays.
This is described as supporting bidirectional mapping, or reverse mapping.

TS
1
2
3
4
5
6
7
8
9
10
11
12
13
// Like, { Sun: 0, Mon: 1, Tue: 2, ... } console.log(Week.Sun) // 0 console.log(Week.Mon) // 1 console.log(Week.Tue) // 2 console.log(Week['Sun']) // 0 console.log(Week['Mon']) // 1 console.log(Week['Tue']) // 2 // Like, ['Sun', 'Mon', 'Tue', ...] console.log(Week[0]) // 'Sun' console.log(Week[1]) // 'Mon' console.log(Week[2]) // 'Tue'

# Implicit assignment

If you do not explicitly assign values when you declare an enum type, numbers starting at 0 and increasing by 1 are assigned automatically (auto-incrementing).

TS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
enum Week { Sun, Mon, Tue, Wed, Thu, Fri, Sat } console.log(Week.Sun) // 0 console.log(Week.Mon) // 1 console.log(Week.Tue) // 2 console.log(Week.Wed) // 3 console.log(Week.Thu) // 4 console.log(Week.Fri) // 5 console.log(Week.Sat) // 6

# Explicit initialization

As follows, you can explicitly initialize the values of some members with the assignment operator (=).
Members without an explicit value are then automatically assigned the previous member's value plus 1.

TS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
enum Week { Sun, Mon, Tue = 7, Wed = 10, Thu = 24, Fri, Sat } console.log(Week.Sun) // 0 console.log(Week.Mon) // 1 console.log(Week.Tue) // 7 console.log(Week.Wed) // 10 console.log(Week.Thu) // 24 console.log(Week.Fri) // 25 console.log(Week.Sat) // 26

# Strings

Enum types mostly use numbers as values, but you can also use strings.
However, string values do not support bidirectional mapping.

TS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
enum Week { Sun = 'Sunday', Mon = 'Monday', Tue = 'Tuesday', Wed = 'Wednesday', Thu = 'Thursday', Fri = 'Friday', Sat = 'Saturday' } console.log(Week.Sun) // 'Sunday' console.log(Week.Mon) // 'Monday' console.log(Week.Tue) // 'Tuesday' console.log(Week.Wed) // 'Wednesday' console.log(Week.Thu) // 'Thursday' console.log(Week.Fri) // 'Friday' console.log(Week.Sat) // 'Saturday' // No bidirectional mapping console.log(Week[0]) // Error - ts(7053) console.log(Week['Sunday']) // Error - ts(7053)

Also, if you use even one string value, you must explicitly initialize every member.
In the following example, Fri and Sat have no explicit initialization, so an error occurs.

TS
1
2
3
4
5
6
7
8
9
enum Week { Sun = 'Sunday', Mon = 'Monday', Tue = 'Tuesday', Wed = 'Wednesday', Thu = 'Thursday', Fri, // Error - ts(1061) Sat // Error - ts(1061) }

# Mixing with numbers

As follows, you can also mix string and number values in an enum's members.
However, this breaks the consistency of the type and makes the code harder to read, so it is not a recommended usage.

TS
1
2
3
4
5
6
7
8
9
enum Week { Sun = 'Sunday', Mon = 'Monday', Tue = 'Tuesday', Wed = 3, Thu = 4, Fri = 5, Sat = 6 }

# const enum

TS
1
2
3
4
5
6
7
8
9
10
11
12
enum Week { Sun, Mon, Tue, Wed, Thu, Fri, Sat } console.log(Week.Sun) // 0 console.log(Week.Mon) // 1
Before compiling

If you compile the enum type in the example above to JavaScript, a bidirectional mapping object (the Week object) is created, as shown below: 0 is assigned to Week["Sun"], "Sun" is assigned to Week[0], and so on.

Week["Sun"] = 0 returns 0.
So Week[Week["Sun"] = 0] is the same as Week[0].

JS
1
2
3
4
5
6
7
8
9
10
11
12
13
"use strict"; var Week; (function (Week) { Week[Week["Sun"] = 0] = "Sun"; Week[Week["Mon"] = 1] = "Mon"; Week[Week["Tue"] = 2] = "Tue"; Week[Week["Wed"] = 3] = "Wed"; Week[Week["Thu"] = 4] = "Thu"; Week[Week["Fri"] = 5] = "Fri"; Week[Week["Sat"] = 6] = "Sat"; })(Week || (Week = {})); console.log(Week.Sun); // 0 console.log(Week.Mon); // 1
After compiling

If you add the const keyword in front when you declare an enum type, the enum definition is removed when the type is compiled, and only the code that uses it is generated inline.
This removes unnecessary code at runtime, so it can help optimize performance.

As in the following example, if you compile the Week enum type declared with the const keyword, you can see that only the values of the members printed to the console (actually used) are generated, and the Week object and the other members are not.

TS
1
2
3
4
5
6
7
8
9
10
11
12
const enum Week { Sun, Mon, Tue, Wed, Thu, Fri, Sat } console.log(Week.Sun) // 0 console.log(Week.Mon) // 1
Before compiling
JS
1
2
3
"use strict"; console.log(0 /* Week.Sun */); // 0 console.log(1 /* Week.Mon */); // 1
After compiling

# Examples

# Order status

The OrderStatus enum represents 5 states, from order received to cancelled.
Then we define a getOrderMessage function that returns a message for each order status.
The function's status parameter is typed to accept an order status value such as OrderStatus.Shipped or 1.

/src/utils/order.ts
TS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
export enum OrderStatus { Pending, // Order received Shipped, // Shipping Delivered, // Delivered Confirmed, // Purchase confirmed Cancelled // Cancelled } export function getOrderMessage(status: OrderStatus) { switch (status) { case OrderStatus.Pending: return 'Your order has been received.' case OrderStatus.Shipped: return 'Your product is being shipped.' case OrderStatus.Delivered: return 'Your product has been delivered.' case OrderStatus.Cancelled: return 'Your order has been cancelled.' default: return 'Unknown status.' } }
/src/views/message.ts
TS
1
2
3
4
5
6
7
8
import { OrderStatus, getOrderMessage } from '@/utils/order' console.log(getOrderMessage(OrderStatus.Shipped)) // 'Your product is being shipped.' console.log(getOrderMessage(OrderStatus.Delivered)) // 'Your product has been delivered.' console.log(getOrderMessage(0)) // 'Your order has been received.' console.log(getOrderMessage(4)) // 'Your order has been cancelled.' console.log(OrderStatus.Pending) // 0 console.log(OrderStatus.Confirmed) // 3

# HTTP status codes

By defining an enum whose values are HTTP status codes, you can clearly distinguish each status, as in HttpStatusCode.Ok (200).

TS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status export enum HttpStatusCode { // Informational Continue = 100, // Everything so far is OK; the client should continue the request, or ignore it if already finished SwitchingProtocols = 101, // The server switches protocols in response to the client's Upgrade request Processing = 102, // The server has received and is processing the request, but the response is not ready yet (WebDAV) EarlyHints = 103, // Used with the Link header; lets the user agent start preloading while the server prepares a response // Successful Ok = 200, // Request succeeded; the meaning depends on the HTTP method (GET, HEAD, PUT, POST, TRACE) Created = 201, // Request succeeded and a new resource was created (usually POST or some PUT) Accepted = 202, // Request received but cannot be processed yet, or an asynchronous response (for another process or batch processing) NonAuthoritativeInformation = 203, // The meta information differs from the origin server and was collected from a local or third-party copy NoContent = 204, // No content; the headers are meaningful and cached headers can be updated ResetContent = 205, // Asks to reset the document view after the request is complete PartialContent = 206, // Used when a Range header requests a partial download MultiStatus = 207, // Conveys status code information for multiple resources (WebDAV) AlreadyReported = 208, // Prevents repeatedly enumerating internal members of the same collection (WebDAV) ImUsed = 226, // GET request fulfilled with instance manipulations applied (HTTP Delta encoding) // Redirection MultipleChoices = 300, // More than one possible response; the user agent should choose one MovedPermanently = 301, // The resource's URI has changed permanently; a new URI may be given Found = 302, // The resource's URI has changed temporarily; keep requesting the same URI SeeOther = 303, // Get the resource with a GET request to another URI NotModified = 304, // For caching; the response has not been modified, so the cached version can be used UseProxy = 305, // Must be accessed through a proxy (deprecated) Unused = 306, // No longer used and reserved TemporaryRedirect = 307, // Request another URI with the same method; like 302, but the method must not change PermanentRedirect = 308, // Permanently moved to another URI; the method must not change // Client errors BadRequest = 400, // The request cannot be understood because of invalid syntax Unauthorized = 401, // Client authentication is required (unauthenticated) PaymentRequired = 402, // Reserved for digital payments, currently unused Forbidden = 403, // The client has no access rights; the server knows the client's identity NotFound = 404, // The requested resource does not exist; may be an API or a hidden resource MethodNotAllowed = 405, // The server knows the method, but it cannot be used NotAcceptable = 406, // No content matches the user agent's criteria ProxyAuthenticationRequired = 407, // Proxy authentication is required RequestTimeout = 408, // The request timed out; the server wants to close the connection Conflict = 409, // The request conflicts with the server's state Gone = 410, // The resource was permanently deleted; caches and links are expected to be removed LengthRequired = 411, // Request rejected because the Content-Length header is not defined PreconditionFailed = 412, // The client's preconditions do not match the server PayloadTooLarge = 413, // The request entity exceeds the server's limits UriTooLong = 414, // The request URI exceeds what the server can handle UnsupportedMediaType = 415, // Unsupported media format RequestedRangeNotSatisfiable = 416, // The requested range is outside the size of the resource ExpectationFailed = 417, // The expectation in the Expect header cannot be met ImATeapot = 418, // Refuses a request to brew coffee in a teapot MisdirectedRequest = 421, // Cannot produce a response for the request URI UnprocessableEntity = 422, // Cannot process the request because of syntax errors (WebDAV) Locked = 423, // Access to the resource is locked (WebDAV) FailedDependency = 424, // The current request failed because a previous request failed (WebDAV) UpgradeRequired = 426, // An upgrade to a different protocol is required PreconditionRequired = 428, // A conditional request is required to prevent lost updates TooManyRequests = 429, // Too many requests in a given amount of time (rate limiting) RequestHeaderFieldsTooLarge = 431, // Request rejected because the header fields are too large UnavailableForLegalReasons = 451, // The resource cannot be accessed for legal reasons // Server errors InternalServerError = 500, // The server ran into a situation it does not know how to handle NotImplemented = 501, // The request method is not supported, except GET and HEAD BadGateway = 502, // The gateway received an invalid response ServiceUnavailable = 503, // Cannot handle the request because of server overload or maintenance GatewayTimeout = 504, // The server acting as a gateway cannot respond in time HttpVersionNotSupported = 505, // The HTTP version of the request is not supported VariantAlsoNegotiates = 506, // Transparent content negotiation leads to a circular reference InsufficientStorage = 507, // Negotiation cannot finish because of a variant resource configuration error LoopDetected = 508, // An infinite loop was detected while processing the request (WebDAV) NotExtended = 510, // Further extensions are needed for the server to fulfill the request NetworkAuthenticationRequired = 511, // Authentication is required for network access } console.log(HttpStatusCode[200]) // 'Ok' console.log(HttpStatusCode[401]) // 'Unauthorized' console.log(HttpStatusCode[500]) // 'InternalServerError' console.log(HttpStatusCode.Ok) // 200 console.log(HttpStatusCode.Unauthorized) // 401 console.log(HttpStatusCode.InternalServerError) // 500