Enums, short for “enumerations”, are a programming language feature that allows developers to define a set of named constants. These constants represent a fixed set of values that a variable can take on. Enums can be used to make code more readable and self-documenting by replacing magic numbers or strings with meaningful names.
Enums are particularly useful when you have a set of related values that you want to group together, such as days of the week, colors, or error codes. By defining an enum, you can ensure that only valid values are used in your code and catch errors at compile time instead of at runtime.
For example, you could define an enum for color with meaningful names such as RED
, GREEN
, and BLUE
. This makes the code more readable and easier to understand.
function draw(color) {
switch (color) {
case Color.RED:
console.log('draw something red')
break;
case Color.GREEN:
console.log('draw something green')
break;
case Color.BLUE:
console.log('draw something blue')
break;
default:
console.log('invalid color')
}
}
draw(Color.GREEN) // draw something green
In JavaScript, there is no built-in support for enums like in other programming languages, but there are a few ways to emulate enums.
const Color = {
RED: 'red',
GREEN: 'green',
BLUE: 'blue'
}
function Enum(values) {
for (let i = 0; i < values.length; i++) {
this[values[i]] = i;
}
this.names = function() {
return Object.keys(this).filter(key => typeof this[key] !== 'function');
}
}
const Color = new Enum(['RED', 'GREEN', 'BLUE']);
const Color = {
RED: Symbol('red'),
GREEN: Symbol('green'),
BLUE: Symbol('blue')
}
class Color {
static RED = new Color('red');
static GREEN = new Color('green');
static BLUE = new Color('blue');
constructor(name) {
this.name = name;
}
toString() {
return this.name;
}
}
const Color = (function() {
const values = {
RED: 'red',
GREEN: 'green',
BLUE: 'blue'
};
const ColorEnum = {};
Object.keys(values).forEach(key => {
Object.defineProperty(ColorEnum, key, {
get: function() {
return values[key];
}
});
});
return ColorEnum;
})();
const Color = new Proxy({}, {
get: function(target, name) {
if (name === 'toJSON') {
return undefined;
}
return name;
}
});
Note that closure-based and proxy-based enums are less common and may not be as widely used as the other approaches mentioned earlier. However, they are still viable options depending on your specific use case.
[TypeScript has native support for enums], which makes it easy to define and use enums in your code. TypeScript enums can be used as types, which means that you can define variables, functions, and parameters with an enum type. This helps to ensure that only valid enum values are used in your code, and can catch errors at compile time instead of at runtime.
enum Direction {
Up,
Down,
Left,
Right,
}
When this code is compiled to JavaScript, it produces the following:
"use strict";
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 = {}));
enum Color {
Red = "red",
Green = "green",
Blue = "blue",
}
When this code is compiled to JavaScript, it produces the following:
"use strict";
var Color;
(function (Color) {
Color["Red"] = "red";
Color["Green"] = "green";
Color["Blue"] = "blue";
})(Color || (Color = {}));
In both cases, TypeScript enums are compiled to JavaScript objects with properties for each enum member. The members are defined using either numeric or string values, and the enum object is augmented with reverse mappings from values to names.
Overall, TypeScript enums provide a more robust and reliable way to define enums in your code than emulating them in JavaScript.