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
- How to Export Transpiled Code From package.json
- Use Nodemon to Restart Your Server on Changes
- How to Allow Trailing Commas (Comma-Dangle) With Typescript-ESLint
- Use SWC to Speed up TypeScript Code
- Fixing Null Type Ignored in Union Type
- How to Remove Index Signature from a Type
- Module Augmentation Overwrites Declarations Instead of Merging Them
- Get All Keys of an Enum
- Get All Values of an Enum
- Using a String as Enum Key
- Understanding “keyof typeof”
- Get Type of Class Properties and Omit Methods
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!