Skip to content
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

Merged
merged 2 commits into from
Jul 6, 2018

Conversation

sandersn
Copy link
Member

This means that in a union like this:

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

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)
Copy link
Member Author

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.

@@ -7048,14 +7049,21 @@ namespace ts {
}
}
else if (isUnion) {
checkFlags |= CheckFlags.Partial;
const index = getIndexInfoOfType(type, IndexKind.String) || (isNumericLiteralName(name) && getIndexInfoOfType(type, IndexKind.Number));
Copy link
Contributor

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...

Copy link
Member Author

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.
@sandersn sandersn merged commit c228924 into master Jul 6, 2018
@sandersn sandersn deleted the index-signatures-contribute-properties-to-union branch July 6, 2018 17:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants