DEV Community

Nhan Nguyen
Nhan Nguyen

Posted on

Beginner's TypeScript #tips

Image description

Typescript enums and why we should avoid them

In the beginner's code bases, we often use Typescript enums to store a bunch of constants.

export enum CompassDirection {
  North, // 0
  East, // 1
  South, // 2
  West, // 3
}
Enter fullscreen mode Exit fullscreen mode

The above code creates a new type CompassDirection with four possible values: CompassDirection.North, CompassDirection.East, CompassDirection.South, and CompassDirection.West.

Each constant gets assigned a numerical value starting at 0, so in that example, CompassDirection.North is equal to 0, and CompassDirection.West is equal to 3.

These values can be customized, and we can use strings, objects, or anything we want instead of numbers:

export enum CompassDirection {
  North = 'N',
  East = 'E',
  South = 'S',
  West = 'W',
}
Enter fullscreen mode Exit fullscreen mode

So Why should we avoid enums? 🤔

We should avoid enums because they are neither convenient nor performant. For instance, this is what the last example gets compiled into by the Typescript compiler:

var CompassDirection;
(function (CompassDirection) {
  CompassDirection['North'] = 'N',
  CompassDirection['East'] = 'E',
  CompassDirection['South'] = 'S',
  CompassDirection['West']= 'W',
})(CompassDirection || (CompassDirection = {}))
Enter fullscreen mode Exit fullscreen mode

That is not pretty, and it comes at the extra cost of all that code being downloaded in the browser and then interpreted, which impacts performance.

Also, enums are not very convenient to be used in component templates. If we want to use an enum in a component template, we need this additional code to make that type accessible on the component instance:

export enum CompassDirection {
  North = 'N',
  East = 'E',
  South = 'S',
  West = 'W',
}

// In Angular Hello Component
@Component({...})
export class HelloComponent {
  compassDirection = CompassDirection;
}
Enter fullscreen mode Exit fullscreen mode

Instead, we could use a union type:

type CompassDirection = 'North' | 'East' | 'South' | 'West'
Enter fullscreen mode Exit fullscreen mode

We still get a type associated with specific values, but now this gets compiled into the following:

Enter fullscreen mode Exit fullscreen mode

We did not forget anything in the above block: Union types are like interfaces and do not get compiled into anything, meaning they do not increase the size of your code base or impact performance.

Also, since those types are just the union of other types (such as strings or numbers), these constants can be used as-is in a component template without needing to tweak our component class.

In other words, union types preserve type safety without degrading our app’s performance, which is a win-win.


I hope you found it useful. Thanks for reading. 🙏

Let's get connected! You can find me on:

Top comments (0)