Before diving into Enums in TypeScript, let's take a second to look at what they are.
Enums are a common type in most popular programming languages, and it means they are a collection of constants.
Enums are great for defining constants that we often re-use and can't be any other than these set values.
Using Enums in TypeScript, we quickly gain the option to see what assignments are valid for that Enum.
Declaring a Enum in TypeScript
To declare an Enum in TypeScript, we have to define the enum
type with a name, much like how we define a interface in TypeScript.
enum Eeveelutions {
Eevee,
Vaporeon,
Jolteon,
Flareon,
Espeon,
Umbreon,
Leafeon,
Glaceon,
Sylveon
};
We can then use this Enum throughout our code by using the following syntax:
const basicPokemon = Eeveelutions.Eevee;
You might be wondering what this will return, right?
The default value for enums is numeric, so this would return 0 as enums start at zero.
But we can also define a different starting order:
enum Eeveelutions {
Eevee = 1,
Vaporeon,
Jolteon,
Flareon,
Espeon,
Umbreon,
Leafeon,
Glaceon,
Sylveon
};
Note that I only added an index on the first item. Everything else now shifts up from there as it will increment from there.
For instance:
const basicPokemon = Eeveelutions.Eevee;
// 1
const Sylveon = Eeveelutions.Sylveon;
// 9
You can use any custom offset. Let's try it with ten and see what happens.
enum Eeveelutions {
Eevee = 10,
Vaporeon,
Jolteon,
Flareon,
Espeon,
Umbreon,
Leafeon,
Glaceon,
Sylveon
};
Which will result in the following:
const basicPokemon = Eeveelutions.Eevee;
// 10
const Sylveon = Eeveelutions.Sylveon;
// 18
However, you might want to give custom values to these enums in some cases.
We might want to assign the Pokemon's number as the value.
enum Eeveelutions {
Eevee = 133,
Vaporeon = 134,
Jolteon = 135,
Flareon = 136,
Espeon = 196,
Umbreon = 197,
Leafeon = 470,
Glaceon = 471,
Sylveon = 700
};
If we ask for specific Pokemon, we will return their respective Pokedex number.
const basicPokemon = Eeveelutions.Eevee;
// 133
const Sylveon = Eeveelutions.Sylveon;
// 700
Changing the value
Numeric might be the default, but we can also assign other values to the Enum.
We can choose between:
- Numeric
- Computed
- String
- Heterogeneous
We've seen numeric in action.
Computed I've actually never really had a use-case for, but you can use functions inside the declaration like this:
const customSize = (input:number) => ( input * 10 )
enum Sizes {
Base = 10,
Medium = Base * 10,
Large = Base * 10 * 100,
Custom = customSize(12)
}
Sizes.Base;
// 10
Sizes.Large;
// 10000
Sizes.Custom;
// 120
It is possible, but I personally never had a good use-case for it.
Then we get to string values, which is a standard option.
We want to have an enum that can be a specific string.
enum RankType {
Date = 'DATE',
Popular = 'POPULAR'
}
RankType.Date;
// 'DATE'
RankType.Popular;
// 'POPULAR'
And the last one is heterogeneous, which means a mix of types, and to be honest, I would strongly urge you not to use this.
It would look something like this:
enum RankType {
Date = 1,
Popular = 'POPULAR'
}
So what happens to these Enums?
You might wonder how they will look once computed to JavaScript, right?
Let's look at the first example and see what will happen when we compile it to JavaScript.
enum Eeveelutions {
Eevee = 133,
Vaporeon = 134,
Jolteon = 135,
Flareon = 136,
Espeon = 196,
Umbreon = 197,
Leafeon = 470,
Glaceon = 471,
Sylveon = 700
};
const basicPokemon = Eeveelutions.Eevee;
console.log(basicPokemon);
const Sylveon = Eeveelutions.Sylveon;
console.log(Sylveon);
Now when compiling this, we generate the following JavaScript version of this script:
var Eeveelutions;
(function (Eeveelutions) {
Eeveelutions[Eeveelutions["Eevee"] = 133] = "Eevee";
Eeveelutions[Eeveelutions["Vaporeon"] = 134] = "Vaporeon";
Eeveelutions[Eeveelutions["Jolteon"] = 135] = "Jolteon";
Eeveelutions[Eeveelutions["Flareon"] = 136] = "Flareon";
Eeveelutions[Eeveelutions["Espeon"] = 196] = "Espeon";
Eeveelutions[Eeveelutions["Umbreon"] = 197] = "Umbreon";
Eeveelutions[Eeveelutions["Leafeon"] = 470] = "Leafeon";
Eeveelutions[Eeveelutions["Glaceon"] = 471] = "Glaceon";
Eeveelutions[Eeveelutions["Sylveon"] = 700] = "Sylveon";
})(Eeveelutions || (Eeveelutions = {}));
;
var basicPokemon = Eeveelutions.Eevee;
console.log(basicPokemon);
var Sylveon = Eeveelutions.Sylveon;
console.log(Sylveon);
So basically, TypeScript converted it into a function that it can call to get the correct index.
You can make this a bit more optimal by converting your enum into a const.
const enum Eeveelutions {
Eevee = 133,
Vaporeon = 134,
Jolteon = 135,
Flareon = 136,
Espeon = 196,
Umbreon = 197,
Leafeon = 470,
Glaceon = 471,
Sylveon = 700
};
const basicPokemon = Eeveelutions.Eevee;
console.log(basicPokemon);
const Sylveon = Eeveelutions.Sylveon;
console.log(Sylveon);
Now when we compile the TypeScript we get the following output:
var basicPokemon = 133 /* Eevee */;
console.log(basicPokemon);
var Sylveon = 700 /* Sylveon */;
console.log(Sylveon);
The code slimmed down a lot!
I hope you enjoyed the article, let me know if you have any questions.
Thank you for reading, and let's connect!
Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter
Top comments (10)
Enums are great for internal use, but are cumbersome when they need to be portable. Once you want to receive them from sources without connection to the enum (e.g. from the server), you need to cast or compare them.
I find the pattern of low-maintenance types better: reuse existing defined structures as type schemas, e.g.
... and the obligatory Objects vs Enums
Fun fact we actually omit enums 99% of the time for objects in our code base.
Love this example you sketched.
Ey there!
side note to your post
We're trying to avoid
Enums
at our current code-base. We've detected that in 99% of the situations the programmer is just looking to type "It's a string, but not any string, just one among these options"In order to avoid ts generating extra code and staying closer to "just adding flavor to js", we're replacing:
from:
to:
Which is what - we - were looking for from the beginning
Nice addition π
I think that's actually an IIFE (function that's invoked immediately) that populates an object (in both directions)
Yep you are actually right there Charles π
I've only started using enums, they make you feel super cool everytime you find a sue case.
I'm actually most of the time looking how to get rid of them.
They do have particular use-cases, but often they can be replaced with an object lookup.
They hold some superpowers for sure, but I personally try to avoid them most cases π
Perhaps function enums are useful for i18n?