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)