Types Of Enums
Numeric Enums
Typescript enums are number-based by default which means they can store string values as numbers.
Example 1:
enum Weekend {
Friday,
Saturday,
Sunday,
}
console.log(Weekend);
Output:

We have an enum named weekend in the above code with three values: Friday, Saturday, and Sunday. By default, Enum values start from zero and are auto-incremented by 1 for each member. However, we can customize these values according to our logic.
Example 2:
public enum Planet {
MERCURY,
VENUS,
EARTH,
MARS,
JUPITER,
SATURN,
URANUS,
NEPTUNE,
PLUTO,
}
console.log(Planet);
Output:

Custom Numeric Enum
Typescript allows declaring the first numeric value of enumerations. Following up on the above example, let’s assign value to Friday as:
Example:
enum Weekend {
Friday = 17,
Saturday,
Sunday,
}
console.log(Weekend);
Output:

Here we still get a sequential pattern if we start the first enumeration with 17, which can be changed by assigning different values to each entity.
String Enums
In typescript, enums can be string type as well. String Enums are important as they improve readability during logging and debugging and possess meaningful values.
The primary difference between numeric enum and string enum is that numeric enums are sequentially auto-incremented, whereas string enums need to be defined individually.
Example 1:
enum Weekend {
Friday = "FRIDAY",
Saturday = "SATURDAY",
Sunday = "SUNDAY",
}
console.log(Weekend);
Output:

Example 2:
enum Planet {
MERCURY = "closest to the sun",
VENUS = "Venus",
EARTH = "Life is possible",
MARS = "Aliens?",
JUPITER = "Largest",
SATURN = "It has nice some rings to it",
URANUS = " ",
NEPTUNE = " ",
PLUTO = "Unavailable",
}
console.log(Planet);
Output:

Heterogenous Enums
It is a mixture of numeric and string enumeration.
Example 1:
enum Weekend {
Friday = "FRIDAY",
Saturday = 2,
Sunday = 4,
}
console.log(Weekend);
Output:

Example 2:
enum Planet {
MERCURY = "closest to the sun",
VENUS = 17,
EARTH = "Life is possible",
MARS = "Aliens?",
JUPITER = 1000,
SATURN = "It has nice some rings to it",
URANUS = 4,
NEPTUNE = 8,
PLUTO = "Unavailable",
}
console.log(Planet);
Output:

Computed and constant members in Enums
Each enum member has a value associated with it which can be either constant or computed.
An enum member is considered constant if:
- If it is a string or numerical enum expression.
- If it is a reference to previously defined constant enumeration.
- If it’s a parenthesized constant enum expression.
- If one of the unary operators (+,-,~) is applied to the expression.
- If one of the binary operators (+, -, *, /, >>>, <<<, ^, &, |) is applied with the expression as an operand.
- If it’s the first member of the enum and has no initializer value. In that case, it is assigned value 0.
Example:
enum institute {
CodingNinjas, // constant
}
console.log(institute);
Output:

Suppose the current enum expression does not have an initializer value, and the preceding enum value is a numeric constant. In that case, the value of the current enum variable will be auto-incremented.
Example:
enum Planets {
mercury = 1,
venus,
earth,
}
Output:

In all the other cases, the expression will be considered computed. Refer to the given example:
Example:
enum Planets {
mercury = 1,
venus = getinfo("It is the second nearest planet to the sun"),
earth = mercury * 40,
}
function getinfo(info: string): number {
if (info === "It is the second nearest planet to the sun") {
return 3000;
}
}
console.log(Planets.venus);
console.log(Planets.earth);
Output:

Enums at Run time
Enums are the real objects that exist at run time. Consider the following example:
Example:
enum E {
X,
Y,
Z,
}
function fun(obj: { X: number }) {
console.log(obj.X);
}
fun(E);
Output:

Enums at Compile time
Even though enums are the real object that exists at runtime, the ‘keyof’ keywords work differently than regular objects.
Consider the following example:
Example:
enum menu {
"Ice-cream",
"shakes",
"burger",
"pizza",
}
type menuStrings = keyof typeof menu;
function display(key: menuStrings, message: string) {
const num = menu[key];
console.log("Menu key is:", key);
console.log("Menu value is:", num);
console.log("Menu message is:", message);
}
display("pizza", "This is the best we have");
Output:

Reverse Mapping in Enums
Enum in typescript support reverse mapping. This means that we can access the value of a member and a member’s name from its value.
Consider the following situation:
Example:
enum display {
"Ice-cream" = 1,
"Shake",
"Burger",
"Bench",
}
console.log(display);
Output:

In the above example, it can be observed that each enum’s value appeared twice. The numeric values can be retrieved from the corresponding enum member and vice-versa. This is known as reverse mapping.
Note: Reverse mapping is not supported for string enum members, whereas in the case of heterogenous enumeration, only numeric type members are supported by reverse mapping.
Ambient Enums
These enums are used to describe the shape of already existing enum types. An ambient enum that does not have an initializer falls under computed enums which is the exact opposite of regular enums.
Example:
declare enum Enum {
X = 1,
Y,
Z = 2,
}
Frequently Asked Questions
Q1: What is the limitation of the enum?
Ans: An enumeration is a type whose value consists of a fixed set of constants. The only limitation of enumeration is although enum types are classes, we can still not define a hierarchy of enums, or we can say that one enum type can’t extend another enum type.
Q2: Can we create enum instances outside of enum?
Ans: No, we cannot create enum instances outside the enum. This is because Enum does not have any public constructor. Since the compiler generates code in response to the enum type declaration, it doesn’t allow public constructors inside Enum, which enforces declaring enum instances inside Enum itself.
Q3: What are the advantages of using Enum as Singleton?
Ans: Enum Singleton looks very promising and handles a lot of stuff, e.g., controlled instance creation, Serialization safety, and it’s easy to create thread-safe singleton using Enum. Singleton enum also helps in double-checking locking and volatile variables.
Key Takeaways
In this blog, we discussed enums in typescript, including their types and properties and some examples to better understand the concept. With enums, we can make our code more readable while organizing our constants into data structure rather than leaving them in the global space.
Also check out - Strong Number
If you are a beginner interested in learning and exploring other fields, you can follow our guided path to understand the core subjects of computers and get a good grip on DSA concepts. In case of any suggestions, feel free to post them in the comments section.