7 TypeScript Tricks with Enum (and Fruits) 🧺
Tags: typescript, programming
Published: 2021-07-27 16:06:10

[Enums](https://www.typescriptlang.org/docs/handbook/enums.html) are one of the key features of [TypeScript](https://www.typescriptlang.org/).

Relying on basic enums, (numeric and auto-incremented) is standard and the most common use case. Yet Enums can offer much more:

* [Merge enums](#merge-enums)
* [Enum subsets](#enum-subsets)
* [Get the keys of an enum](#enum-get-keys)
* [Get the values of an enum](#enum-get-values)
* [Iterate over an enum keys](#iterate-over-enum-keys)
* [Iterate over an enum values](#iterate-over-enum-values)
* [const enum](#const-enum)

---

In the rest of this post, let's assume the following code is available:

```ts
enum Fruit {
  APPLE = '🍎',
  BANANA = '🍌',
  CHERRY = '🍒',
}
```

---

### 1. Merge enums <a name="merge-enums"></a>

Merging enums is pretty straightforward using the pipe `|` operator:

```ts
enum OtherFruit {
  DATE = 'date',
}

type AnyFruit = Fruit | OtherFruit
```

[▶️ Try on TypeScript Playground](https://www.typescriptlang.org/play?#code/KYOwrgtgBAYgTmAlgFygbwFBSgQQAp4AyAolALxQDkgPBuBy+5QDRZQBCOAchzuVdYDL7jZgGEAEsQBK4gJo8agJX3BAXwwZkATwAOwKFMgQ18JMgDOPYgA8AxgBswAE2AAeQygawEKAHSiJ0gHwYAPSB5H5Q6lo6egYeJjwuyJ74RKQAPu5GnmycnBhAA)

---

### 2. Enum subsets <a name="enum-subsets"></a>

Because cherries may not be as tasty as other fruits, let's exclude them:

```ts
type YummyFruits = Exclude<Fruit, Fruit.CHERRY>
// => type YummyFruits = Fruit.APPLE | Fruit.BANANA
```

[▶️ Try on TypeScript Playground](https://www.typescriptlang.org/play?#code/KYOwrgtgBAYgTmAlgFygbwFBSgQQAp4AyAolALxQDkgPBuBy+5QDRZQBCOAchzuVdYDL7jZgGEAEsQBK4gJo8agJX3BAXwwZkATwAOwKFMgQ18JMgDOPYgA8AxgBswAE2AAeQygawEKAHSiJ0gHwYAPSB5H5Q6lo6egYeJjwuyJ74RKQAPu5GnmycnBhAA)

---

### 3. Get the keys of an enum dynamically <a name="enum-get-keys"></a>

This one needs the use of two type operators: [`keyof`](https://www.typescriptlang.org/docs/handbook/2/keyof-types.html#the-keyof-type-operator) and [`typeof`](https://www.typescriptlang.org/docs/handbook/2/typeof-types.html#the-typeof-type-operator).

```ts
type FruitKey = keyof typeof Fruit
// => type FruitKey = "APPLE" | "BANANA" | "CHERRY"

const keys = Object.keys(Fruit) as FruitKey[]
// => ["APPLE", "BANANA", "CHERRY"]
```

[▶️ Try on TypeScript Playground](https://www.typescriptlang.org/play?#code/KYOwrgtgBAYgTmAlgFygbwFBSgQQAp4AyAolALxQDkgPBuBy+5QDRZQBCOAchzuVdYDL7jZgGEAEsQBK4gJo8agJX3BAXwwZkATwAOwWAhQBpYGp4BrQwHsAZlHVbLOpMgwB6J+QB81zdvgODRigBE+ETEAVAAPlABbJycYZEBohLSASoAxmYgAM6opmpZPADyAEYAVsBpyAB0eVkAFD4oAJRQAIYFjch+ANoAus6uZB7dQQQkAQxRMVwTUUmSUgH9QA)

---

### 4. Get the values of an enum dynamically <a name="enum-get-values"></a>

This snippet leverages the [Template Literal](https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html) type operator:

```ts
type FruitValue = `${Fruit}`
// => type FruitValue = "🍎" | "🍌" | "🍒"

const values: FruitValue[] = Object.values(Fruit)
// => ["🍎", "🍌", "🍒"]
```

[▶️ Try on TypeScript Playground](https://www.typescriptlang.org/play?#code/KYOwrgtgBAYgTmAlgFygbwFBSgQQAp4AyAolALxQDkgPBuBy+5QDRZQBCOAchzuVdYDL7jZgGEAEsQBK4gJo8agJX3BAXwwZkATwAOwWAhQA1AIYAbMNooADACRp4SZIvMYA9E-IA+KOq067hk2agAIjpAqAAfIP5QiOC5QJUAYwB7EABnVAA3Y1NUgC4ffWzgAG0AXR4AeQAjACtgBOQAOiz-VIAKWxQASmdXMg9i4NpAhki+Eci40owgA)

---

### 5. Iterate over an enum keys <a name="iterate-over-enum-keys"></a>

Looping through the enum keys is as simple as:

```ts
for (let fruit of Object.keys(Fruit)) {
  console.log(fruit)
}
// => APPLE
//    BANANA
//    CHERRY
```

[▶️ Try on TypeScript Playground](https://www.typescriptlang.org/play?#code/KYOwrgtgBAYgTmAlgFygbwFBSgQQAp4AyAolALxQDkgPBuBy+5QDRZQBCOAchzuVdYDL7jZgGEAEsQBK4gJo8agJX3BAXwwYAZgHs4UABQAbYKlUIUUdaqgB5AEYArYAGNkAOgDWwAJ4BnbfCTIAlP7ozPbqIJ7q+k666gDm2kZ+-hjKAPSp5AB8uAQkGOnY2GycnPkZhaIS0hhAA)

---

### 6. Iterate over an enum values <a name="iterate-over-enum-values"></a>

In the same spirit, looping through the enum values:

``` ts
for (let fruit of Object.values(Fruit)) {
  console.log(fruit)
}
// => 🍎
//    🍌
//    🍒
```

[▶️ Try on TypeScript Playground](https://www.typescriptlang.org/play?#code/KYOwrgtgBAYgTmAlgFygbwFBSgQQAp4AyAolALxQDkgPBuBy+5QDRZQBCOAchzuVdYDL7jZgGEAEsQBK4gJo8agJX3BAXwwYAZgHs4UABQAbYKlUIUUdaqgB5AEYArYAGNkAOgBuAQ11hgAZ23wkyACUgejM9uog3ur6TrrqAObaRgGBGMoA9OnkAHxQdBiZ2Nj8BVlF1HIYQA)

---

### 7. `const enum` <a name="const-enum"></a>

By default, enums generate a bunch of code when compiled to JavaScript:

```js
var Fruit;
(function (Fruit) {
    Fruit["APPLE"] = "🍎";
    Fruit["BANANA"] = "🍌";
    Fruit["CHERRY"] = "🍒";
})(Fruit || (Fruit = {}));
```

There is however a way not to generate this much code: by leveraging `const enum`.

Adding just a `const` in front of our Fruit enum makes a big difference:

```ts
const enum Fruit {
  APPLE = '🍎',
  BANANA = '🍌',
  CHERRY = '🍒',
}
```

...as it compiles to nothing. 🕳️

Just until we use part of its values:

```ts
const chosenFruit = Fruit.BANANA
// => compiles to:
// var chosenFruit = "🍌";
```

[▶️ Try on TypeScript Playground](https://www.typescriptlang.org/play?#code/MYewdgzgLgBApmArgWxgMQE6IJawN4BQMMAggApkAyAojALwwDkgPBuBy+4wDREwBCJAcgJL0mzQDL7nbgGEAEtQBK8gJoiWgJX3JAXwIFQkWMAAWICAkw5YDc7gB0fQYIIB6J-QB8MUMgAO2ADZwEDBQIABczq4AbgCGGJ7GpmDWljAAROKpANwEQA)