d
Amit DhamuSoftware Engineer
 

Use as const to create union type

3 minute read 00000 views

Using as const on an object in Typescript can be a useful way of creating a union type.

Take the example code below:

const availableCars = {
  bmw: 'BMW',
  porsche: 'PORSCHE',
  mercedes: 'MERCEDES',
}

const takeForTestDrive = (car: string) => {
  console.log(car)
}

You can probably see the problem already. We don't really want string as the argument for car in the takeForTestDrive function. It would mean we could do the following and Typescript wouldn't complain:

takeForTestDrive('FERRARI')

This is because each value in the availableCars is a string so any string is permittable.

We could create a manual type union:

const takeForTestDrive = (car: 'BMW' | 'PORSCHE' | 'MERCEDES') => {
  console.log(car)
}

However, each time we added or removed a car, we would also have to update the availableCars object.

Instead, we could change our object to use as const:

const availableCars = {
  bmw: 'BMW',
  porsche: 'PORSCHE',
  mercedes: 'MERCEDES',
} as const

This will change all properties of the object to readonly and set the type of each item to their literal values. We could then leverage keyof and typeof to dynamically create a union type for our function:

const takeForTestDrive = (
  car: typeof availableCars[keyof typeof availableCars]
) => {
  console.log(car)
}

Now, any time you call takeForTestDrive, you will only be able to do so using either BMW, PORSCHE or MERCEDES.

Alternative - Use an enum

Here's an alternative option which uses an enum. Doing this would change the function signature in a way where you would be permitted to using the enum when calling the function rather than being able to pass a string even if it matches the string that's set on the enum value.

enum availableCars {
  bmw = 'BMW',
  porsche = 'PORSCHE',
  mercedes = 'MERCEDES',
}

const takeForTestDrive = (car: availableCars) => {
  console.log(car)
}

takeForTestDrive(availableCars.bmw) // works

takeForTestDrive('BMW') // Argument of type '"BMW"' is not assignable to parameter of type 'availableCars'