1. What Are TypeScript Enums?
Enums in TypeScript let you define a set of named constants. While this might sound convenient, enums often include hidden complexities that can affect performance and debugging.
1enum Environment {
2 PRODUCTION = "PRODUCTION",
3 DEVELOP = "DEVELOP",
4 STAGE = "STAGE"
5}
At first glance, this simple code snippet may appear harmless. However, enums can generate extra JavaScript code during the transpilation process, which can result in complex debugging issues and differences across various build environments.
1export var Environment;
2(function (Environment) {
3 Environment["PRODUCTION"] = "PRODUCTION";
4 Environment["DEVELOP"] = "DEVELOP";
5 Environment["STAGE"] = "STAGE";
6})(Environment || (Environment = {}));
This is what a typescript enum is compiled into. Why like this? To answer this question we have to go deeper that this example. What would happen if we would have this as an enum?
1enum Environment {
2 PRODUCTION,
3 DEVELOP,
4 STAGE
5}
What do you think would happen when this gets compiled?
1"use strict";
2var Environment;
3(function (Environment) {
4 Environment[Environment["PRODUCTION"] = 0] = "PRODUCTION";
5 Environment[Environment["DEVELOP"] = 1] = "DEVELOP";
6 Environment[Environment["STAGE"] = 2] = "STAGE";
7})(Environment || (Environment = {}));
8
Not what you've expected, right? This output might confuse you even more, but when you convert a Environment enum into an object you get this output
1{
2 "0": "PRODUCTION",
3 "1": "DEVELOP",
4 "2": "STAGE",
5 "PRODUCTION": 0,
6 "DEVELOP": 1,
7 "STAGE": 2
8}
That is why there are number assignations, those numbers represent an index inside the enum.
How do you use enum as a type?
1const getEnvironmentData = (env: Environment)=>{}
2
3// Works ✅
4getEnvironmentData(0)
5getEnvironmentData(Environment.PRODUCTION)
6
7// Doesn't work ❌
8getEnvironmentData("PRODUCTION")
There is a way to remove the additional code overhead by using
1const enum Environment {
2 PRODUCTION = "PRODUCTION",
3 DEVELOP = "DEVELOP",
4 STAGE = "STAGE"
5}
But this introduces additional edge case issues because this removes the whole object in the runtime.
2. Introducing Typed Objects
Typed objects utilize the as const
feature in TypeScript, ensuring that the values remain literal types. This approach offers clarity and keeps your JavaScript output predictable.
1const Environment = {
2 PRODUCTION: "PRODUCTION",
3 DEVELOPMENT: "DEVELOPMENT",
4 STAGE: "STAGE"
5} as const;
By using this as const
annotation, each value in the object is treated as a literal type, maintaining type safety without the overhead that comes with enums. When compiled this is the output, no additional code.
While this removes additional complexity from the end compiled code, raw object can't be used as a type directly, we need to do some type manipulation. To use it as type in a way enum is used additional code is needed.
1const Environment = {
2 PRODUCTION: "PRODUCTION",
3 DEVELOPMENT: "DEVELOPMENT",
4 STAGE: "STAGE"
5} as const;
6
7type TEnviroment = typeof Environment[keyof typeof Environment]
8
9const getEnvironmentData = (env: TEnviroment)=>{}
This is how to get the type out of the object, now how do we use it?
1const getEnvironmentData = (env: TEnviroment)=>{}
2
3getEnvironmentData('PRODUCTION')
4getEnvironmentData(Environment.PRODUCTION)
As you can see, you can type it like an enum, but then again you can provide it a string version of the value as in this case "PRODUCTION" is also a valid type. This means you don't need an additional import just for you to get the enum value.
Conclusion
This doesn't means that you can't or shouldn't use enums anymore. This blog post is about showing you that there are other, better solutions.
By using typed objects instead of enums, you gain:
- Cleaner transpilation
- Easier debugging
- Better type safety
- Streamlined code maintenance
At AS Agency, we believe these benefits contribute to building scalable, reliable, and future-proof applications. Typed objects are just one example of how we stay on the cutting edge of TypeScript best practices to deliver top-quality web development services for our clients.