D. Pardal
D. Pardal

Reputation: 6597

ts(1170) error with mapped type when a new property is added

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

Answers (1)

jcalz
jcalz

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

Playground link to code

Upvotes: 9

Related Questions