Skip to content

Index signatures contribute properties to unions#25307

Merged
sandersn merged 2 commits into
masterfrom
index-signatures-contribute-properties-to-union
Jul 6, 2018
Merged

Index signatures contribute properties to unions#25307
sandersn merged 2 commits into
masterfrom
index-signatures-contribute-properties-to-union

Conversation

@sandersn
Copy link
Copy Markdown
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
>bbb : Symbol(bbb, Decl(use.js, 5, 3))
>mod.Baz : Symbol(Baz)
>mod : Symbol(mod, Decl(use.js, 0, 3))
>Baz : Symbol(Baz)
Copy link
Copy Markdown
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.

Comment thread src/compiler/checker.ts Outdated
}
else if (isUnion) {
checkFlags |= CheckFlags.Partial;
const index = getIndexInfoOfType(type, IndexKind.String) || (isNumericLiteralName(name) && getIndexInfoOfType(type, IndexKind.Number));
Copy link
Copy Markdown
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
Copy Markdown
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
@microsoft microsoft locked as resolved and limited conversation to collaborators Oct 21, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants