Typescript trick: Required enum values as keys


Let’s say we have an string enum in TypeScript, and we want to use those enum values as keys in another object.

There’s potential that we might forget to add a matching entry to our object when updating or renaming a member of the enum, which may not be desirable. This post describes a quick trick to ensure this at compile time.

Typescript Type

Instead of Record<Key1|Key2, ValueType>, we can use the EnumRecord<MyEnum, ValueType> on our record, and it will require that all of the values of the enum are exhaustively defined as members in our object:

type EnumRecord<KeyType extends string, ValueType> = {[key in KeyType]: ValueType};

In practice

For a practical example, we could have some code like this:

// require all enum keys on record
type EnumRecord<KeyType extends string, ValueType> = {[key in KeyType]: ValueType};

// some keys to use
enum FeatureFlagKeys {
  DarkMode = 'dark_mode'
  DashboardMetrics = 'dashboard_metrics'
  CommentsView = 'comments_view'

// an object using enum values as keys
const FlagMetadata : EnumRecord<FeatureFlagKeys, { title: string }> = {
  [FeatureFlagKeys.DarkMode]: { title: 'Dark Mode' },
  [FeatureFlagKeys.DashboardMetrics]: { title: 'Enhanced Dashboard Metrics' },

Resulting Error

When we compile the above example, this will yield an error on typescript compilation, since FeatureFlagKeys.CommentsView is missing:

Property '[FeatureFlagKeys.CommentsView]' is missing in type '{ dark_mode: { title: string; }; dashboard_metrics: { title: string; }; }' but required in type 'EnumRecord<FeatureFlagKeys, { title: string; }>'. ts(2741)

Change Log

  • 4/6/2024 - Initial Revision

Found a typo or technical problem? file an issue!