TypeScript — Using a String as Enum Key

TypeScript enums are similar to JavaScript objects. They store a named set of constants. Enums can also store a key-value pair. You can access the values with a string-like value. It’s “string-like” because enums are more strict in types and require a specific string value: one of the available keys.

This tutorial shows you how to use a string value as an enum key to access the related value.

TypeScript Series Overview

Using a String to Access Enum Values in TypeScript

Enums represent a defined set of constants with specific keys and values. You can dynamically access enum values by using the related keys. But you must only use the enum’s keys, you can’t use a string value.

Here’s an example of a FutureStudioBooks enum. It’s a slug-title pair. You can access the title by using the related slug. Look at this code snippet that retrieves the title for the Retrofit book by using the "retrofit" key:

export enum FutureStudioBooks {  
  retrofit = 'Retrofit Book',
  picasso = 'Picasso Book',
  glide = 'Glide Book',
  gson = 'Gson Book',
  'gson-workbook' = 'Gson Workbook',
}

const key = 'retrofit'  
const book = FutureStudioBooks[key]  
// the type of `book` is "const book: FutureStudioBooks.retrofit"

This works correctly with TypeScript because the type of key is the precise value "retrofit". It’s not the broad “string” value exact value:

const key = 'retrofit'  
// the type of `key` is "const key: "retrofit""

If you’re changing the type of key to a string, TypeScript fails because enums are not an index type and you can’t use a string value for indexed access:

const key: string = 'retrofit'  
const title = FutureStudioBooks[key]  
// 🚨 Element implicitly has an 'any' type because expression of type 'string'
// can't be used to index type 'typeof FutureStudioBooks'. No index signature
// with a parameter of type 'string' was found on type 'typeof FutureStudioBooks'.ts(7053)

You can see that you must use a valid key from one of the available key values "retrofit" or "picasso" or "glide", and so on. For indexed access, even with a “string-like” value, you must use one of the available keys. And you can create a union type of the available keys and use it to retrieve related values.

You can define a union type of the keys manually or dynamically. Manually defining the keys creates a second place that you need to maintain in your code. The first place is the enum itself and the second is your type for the keys. A dynamically created union type of enum keys is more convenient.

Here’s the code of both ways to create a union type for the enum keys:

type FutureStudioBooksKey = "retrofit" | "picasso" | "glide" | "gson" | "gson-workbook"

// or

type FutureStudioBooksKey = keyof typeof FutureStudioBooks;  
// type FutureStudioBooksKey = "retrofit" | "picasso" | "glide" | "gson" | "gson-workbook"

We prefer the keyof typeof way for the enum key type. You can then use it as the actual type or type assertions in your code:

export enum FutureStudioBooks {  
  retrofit = 'Retrofit Book',
  picasso = 'Picasso Book',
  glide = 'Glide Book',
  gson = 'Gson Book',
  'gson-workbook' = 'Gson Workbook',
}

type FutureStudioBooksKey = keyof typeof FutureStudioBooks;  
// type FutureStudioBooksKey = "retrofit" | "picasso" | "glide" | "gson" | "gson-workbook"

const key: FutureStudioBooksKey = 'retrofit'  
const title = FutureStudioBooks[key]  
// ✅ works!
// const value: FutureStudioBooks.retrofit

Enjoy!

Explore the Library

Find interesting tutorials and solutions for your problems.