DEV Community

Cover image for How to write a constant in the TypeScript?
Przemyslaw Jan Beigert
Przemyslaw Jan Beigert

Posted on • Updated on

How to write a constant in the TypeScript?

Introduction

TypeScript was designed as a superset of JavaScript, so TS types should not affect JS’s runtime. However there’s couple ways to define constant value.

Object as const:

export const BUTTON_SIZES = {
  SMALL: 'small',
  MEDIUM: 'medium',
  LARGE: 'large',
} as const;
Enter fullscreen mode Exit fullscreen mode

as const will be removed in the compilation time, so only an object will exists in the run time. Adding as const will change type definition from:

{ 
  SMALL: string,
  MEDIUM: string,
  LARGE: string,
}
Enter fullscreen mode Exit fullscreen mode

into:

{
  readonly SMALL: 'small',
  readonly MEDIUM: 'medium',
  readonly LARGE: 'large',
}
Enter fullscreen mode Exit fullscreen mode

Looks pretty simple however it wouldn’t be so easy to create a type definition of BUTTON_SIZES value.

type ButonSizeKey = keyof typeof BUTTON_SIZES; // "SMALL" | "MEDIUM" | "LARGE"
type ButonSizeValue = typeof BUTTON_SIZES[ButonSizeKey] // "small" | "medium" | "large"
Enter fullscreen mode Exit fullscreen mode

Enum:

export enum BUTTON_SIZES_ENUM {
  SMALL = 'small',
  MEDIUM = 'medium',
  LARGE = 'large',
};
Enter fullscreen mode Exit fullscreen mode

Looks similar to the previous case however this code will be complied into:

export var BUTTON_SIZES_ENUM;
(function (BUTTON_SIZES_ENUM) {
  BUTTON_SIZES_ENUM["SMALL"] = "small";
  BUTTON_SIZES_ENUM["MEDIUM"] = "medium";
  BUTTON_SIZES_ENUM["LARGE"] = "large";
})(BUTTON_SIZES_ENUM || (BUTTON_SIZES_ENUM = {}));
Enter fullscreen mode Exit fullscreen mode

It’s the same object as in previous case but it takes more space in the final bundle.

Big advantage is the fact that you don’t have to create a separate type for a ButtonSizeValue because enum BUTTON_SIZE can be use as a type of a value.

But what about case when enum has numbers instead of strings:

export enum PLACE {
  FIRST = 1,
  SECOND = 2,
};
Enter fullscreen mode Exit fullscreen mode

Will be complied to:

export var PLACE;
(function (PLACE) {
  PLACE[PLACE["FIRST"] = 1] = "FIRST";
  PLACE[PLACE["SECOND"] = 2] = "SECOND";
})(PLACE || (PLACE = {}));
Enter fullscreen mode Exit fullscreen mode

And this code it the same that:

{1: "FIRST", 2: "SECOND", FIRST: 1, SECOND: 2}
Enter fullscreen mode Exit fullscreen mode

So value become a key and key becomes a value…

Const enum:

export const enum BUTTON_SIZES_CONST_ENUM {
  SMALL = 'small',
  MEDIUM =  'medium',
  LARGE = 'large',
};
Enter fullscreen mode Exit fullscreen mode

Almost the same code as in the previous example will be removed in compilation time.

Usage of enum like this:

const buttonSizeUsage = BUTTON_SIZES_CONST_ENUM.MEDIUM;
Enter fullscreen mode Exit fullscreen mode

Will be complied into:

const buttonSizeUsage = "medium" /* MEDIUM */;
Enter fullscreen mode Exit fullscreen mode

Looks much better than previous example however there’s couple od disadvantages:

const obj = { buttonSize: BUTTON_SIZES_CONST_ENUM } // ERROR: 'const' enums can only be used in property or index access expressions or the right hand side of an import declaration or export assignment or type query.
Object.values(BUTTON_SIZES_CONST_ENUM); // ERROR 'const' enums can only be used in property or index access expressions or the right hand side of an import declaration or export assignment or type query.
Enter fullscreen mode Exit fullscreen mode

Union:

The simplest way will be:

type BUTTON_SIZES_UNION = "small" | "medium" | "large";
Enter fullscreen mode Exit fullscreen mode

Type definition will be removed in compilation time and complier will prevent us to pass unknown or different strings.

let fn = (buttonSize: BUTTON_SIZES_UNION) => {};
fn('small');
fn('smal'); // Argument of type '"smal"' is not assignable to parameter of type 'BUTTON_SIZES_UNION'
let str: string;
fn(str); // Argument of type 'string' is not assignable to parameter of type 'BUTTON_SIZES_UNION'.
Enter fullscreen mode Exit fullscreen mode

Is fast in the implementation but has the same disadvantages as const enum. Also changing value (e.g. “medium” into “regular”) requires modification of each usage, not just one like in enum/const enum.

Summary:

Is hard to choose the best way, all of them have advantages and disadvantages. In my opinion const enum can be good first choice.

Playground

Top comments (0)