Skip to main content

enums VS as consts

· 3 min read
Marcus Koh

I personally have not used enums much in my professional experience because I find them difficult to understand and I can't clearly visualise their data structure during development of mobile apps.

Recently, I have stumbled upon this particular youtube video that has piqued my interest in understanding enums vs as consts in Typescript.

Enums

I have decided to generate some examples based on my past experience.

Let's assume you have an enum called Branches, it stores a mapping between the semantic name to their actual id.

enum Branches  {
MAIN = 1000,
WOODLANDS = 1001,
ADMIRALTY = 1002,
SEMBAWANG = 1003,
}

When typescript compiles it, it becomes:

var BranchesEnum;
(function (BranchesEnum) {
BranchesEnum[BranchesEnum["MAIN"] = 1000] = "MAIN";
BranchesEnum[BranchesEnum["WOODLANDS"] = 1001] = "WOODLANDS";
BranchesEnum[BranchesEnum["ADMIRALTY"] = 1002] = "ADMIRALTY";
BranchesEnum[BranchesEnum["SEMBAWANG"] = 1003] = "SEMBAWANG";
})(BranchesEnum || (BranchesEnum = {}));

This is really hard to read right? In reality, this is how it looks like:

const Branches = {
MAIN: 1000,
1000: 'MAIN',
WOODLANDS: 1001,
1001: 'WOODLANDS',
ADMIRALTY: 1002,
1002: 'ADMIRALTY',
SEMBAWANG: 1003,
1003: 'SEMBAWANG',
}

It has a 2-way mapping between the key-value and value-key.

Let's say you have a function to "open the branch"

function openBranchEnum(branch: BranchesEnum) {
console.log(branch);
}

Then the only way you can open this branch is via

openBranchEnum(BranchesEnum.MAIN);

Let's say to open a branch, you have to call an api to know the branch code, then that becomes abit more complicated.

const { response } = await api();
const branchCode = response.data.branchCode; // 1000

// key is of type "MAIN" | "WOODLANDS" | "ADMIRALTY" | "SEMBAWANG"
let key = BranchesEnum[1000] as keyof typeof BranchesEnum; // key = MAIN
openBranchEnum(BranchesEnum[key]);

This is quite annoying and troublesome because you still have to find the key and make sure to type-cast it properly or else, key will be of type string.

as const

Following the same example as above:

const BRANCHES = {
MAIN: 1000,
WOODLANDS: 1001,
ADMIRALTY: 1002,
SEMBAWANG: 1003,
} as const

type ValueOf<T> = T[keyof T];

type Branches = ValueOf<typeof BRANCHES>;

function openBranches (branch: Branches) {
console.log(branch);
}

const { response } = await api();
const branchCode = response.data.branchCode; // 1000

openBranches(1000);

Using as const is so much easier on the mental load and you do not need to worry about any conversion between types.