Index signatures contribute properties to unions#25307
Conversation
This means that in a union like this:
```ts
type T = { foo: number } | { [s: string]: string }
```
`foo` is now a property of `T` with type `number | string`. Previously
it was not.
Two points of interest:
1. A readonly index signature makes the resulting union property readonly.
2. A numeric index signature only contributes number-named properties.
Fixes #21141
| >bbb : Symbol(bbb, Decl(use.js, 5, 3)) | ||
| >mod.Baz : Symbol(Baz) | ||
| >mod : Symbol(mod, Decl(use.js, 0, 3)) | ||
| >Baz : Symbol(Baz) |
There was a problem hiding this comment.
mod is a union; one constituent has Baz: any and the other has a string index signature to any (as is commonly provided in JS). The union therefore now has a property Baz, although its type is still any.
| } | ||
| else if (isUnion) { | ||
| checkFlags |= CheckFlags.Partial; | ||
| const index = getIndexInfoOfType(type, IndexKind.String) || (isNumericLiteralName(name) && getIndexInfoOfType(type, IndexKind.Number)); |
There was a problem hiding this comment.
this would include symbols too...
There was a problem hiding this comment.
Specifically (from our discussion) symbol-named properties should not check index signatures, numeric-named properties should use the number index signature (if present); then they and all other properties should check for a string index signature. Similar code should already exist in the code that gets the index type for a property that's not found in element access lookup.
Here's an example:
const sym = symbol()
declare const o : { [s: string]: string | number, [n: number]: number } | { s: number, 1: number, [sym]: boolean }
o["s"] // : string | number
o["1"] // : number
o[sym] // : any + error1. Symbol-named properties don't contribute to unions. 2. Number-named properties should use the numeric index signature type, if present, and fall back to the string index signature type, not the other way round.
This means that in a union like this:
foois now a property ofTwith typenumber | string. Previouslyit was not.
Two points of interest:
Fixes #21141