Reputation: 849
Let's say I have a simple enum
enum MyEnum {
a,
b,
c
}
Mapping the enum into a key value const is simple:
type A<V> = { [k in MyEnum]: V };
const testA: A<string> = {
[MyEnum.a]: '',
[MyEnum.b]: '',
[MyEnum.c]: ''
};
The problem starts when I am trying to pass the enum as a generic type:
type B1<T, V> = { [k in T]: V } // that won't work
const testB: A<MyEnum , string> = { ... } // usage
I tried few approaches ideas in this play-ground
There are some similar question (listed bellow) but I still got the feeling that in this particular example if the first option (type A<V> = { [k in MyEnum]: V };
) is possible the other options should be too (type B1<T, V> =
).
Mapping Enum to Type of keys or values
is-it-possible-to-allow-literal-string-values-with-typescripts-enum-type
Upvotes: 1
Views: 306
Reputation: 15106
The error message on type B1<T, V> = { [k in T]: V }
says Type 'T' is not assignable to type 'string | number | symbol'.
, which can be remedied by adding a constraint to T
:
type B<T extends PropertyKey, V> = { [k in T]: V }
(using the built-in type PropertyKey = string | number | symbol
)
Now you can pass the enum to B
as a generic argument:
const testB: B<MyEnum, string> = {
[MyEnum.a]: 'aa',
[MyEnum.b]: 'bb',
[MyEnum.c]: 'cc'
};
Or, as Alex Wayne suggested, you can forego declaring B
altogether and just use the built-in Record
type. It's definition is
type Record<K extends keyof any, T> = {[P in K]: T}
which is equivalent to B
, as keyof any
is string | number | symbol
, just like PropertyKey
.
Upvotes: 2