Reputation: 28757
Using typescript Version 3.7.5. I have these two simple types and I would expect that either both of them compile or neither do. However, typescript only complains about the second one. Why is the second type invalid, but the first isn't?
// this works
type foo = {
[key in 'xxx']: number
}
// this does not
type bar = {
xxx: number
[key in 'xxx']: number
}
Here are the compiler messages:
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)
The right-hand side of an 'in' expression must be of type 'any', an object type or a type parameter.ts(2361)
See the code in action in the typescript playground.
Upvotes: 1
Views: 3261
Reputation: 15116
The first definition is a mapped type (doc), which binds key
, so you can use it in the right-hand side, e.g.:
type foo = {
[key in 'xxx']: key
}
You cannot add properties to mapped types though. For example, for
type foo = {
[key in 'xxx']: key
xxx: number
}
TypeScript will show an error about an expected }
at the position of xxx
.
On the other hand,
type bar = {
xxx: number
[key in 'xxx']: number
}
is a regular type literal, in which [key in 'xxx']: number
is a computed property, for which the restrictions mentioned in the first two error messages hold.
The third error message comes from TypeScript interpreting in
as the regular expression-level in
. You can see the same error here:
const error = key in 'xxx'
(and if you hover over key
in your second example, you'll also see a Cannot find name 'key'.
error)
Upvotes: 2