-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Index signatures contribute properties to unions #25307
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
>mod : Symbol(mod, Decl(use.js, 0, 3)) | ||
>Baz : Symbol(Baz) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
src/compiler/checker.ts
Outdated
@@ -7048,14 +7049,21 @@ namespace ts { | |||
} | |||
} | |||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this would include symbols too...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 + error
1. 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:
foo
is now a property ofT
with typenumber | string
. Previouslyit was not.
Two points of interest:
Fixes #21141