Reputation: 6597
I have the following code:
enum A {
FOO = 0,
BAR = 1,
BAZ = 2
}
type B = {
[key in A]: number
}
declare let b: B;
It works fine. I can use b[A.FOO]
but not b[123]
. However, I'd like to also be able to use b.length
, but when I add a property to type B
, like so...
type B = {
length: number,
[key in A]: number
}
...I get the following errors
A computed property name in a type literal must refer to an expression whose type is a literal type or a 'unique symbol' type.ts(1170) A computed property name must be of type 'string', 'number', 'symbol', or 'any'.ts(2464)
How can I solve this?
Upvotes: 6
Views: 2626
Reputation: 328788
You have discovered that a mapped type of the form {[K in XXX]: YYY}
does not allow additional properties. Luckily, you can get the same effect by using an intersection type; an intersection of two object types has all the properties from both:
type B = {
[key in A]: number
} & { length: number };
In your specific case, since all these properties are of type number
, you could also use a single mapped type where the key type is the union of the A
enum values and the literal type "length"
:
type B = {
[key in A | "length"]: number;
}
Both versions will work as you desire:
let b: B = {
[A.FOO]: 12,
[A.BAR]: 34,
[A.BAZ]: 56,
length: 78
} // okay
Upvotes: 9