microsoft / microsoft/TypeScript
Writes to indexed access of an index signature are not sufficiently constrained
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 111k
- Forks
- 14.3k
- Avg merge
- 2d 4h
- Merged PRs (30d)
- 132
Description
🔎 Search Terms
"return type" "generic" "type parameter" "indexed access" "index signature" "assignable" "constraint"
🕗 Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about index signatures
⏯ Playground Link
💻 Code
type Example = {
a: 'a'
[key: string]: string
}
declare const example: Example
const key1: string = 'a'
example[key1] = 'not a' // no error
declare const key2: 'a' | 'b'
example[key2] = 'not a' // error, as expected
//^^^^^^^^^^^
// Type '"not a"' is not assignable to type '"a"'.
🙁 Actual behavior
The index signature allows any string value to be assigned, ignoring the narrower type of a.
🙂 Expected behavior
Both property assignments in the above code should raise errors, for the same reason.
Additional information about the issue
This is a more generalized version of #60700. @MartinJohns helped me realize that type parameters need not be involved.
Here's another pair of examples (1, 2) which I expected to be reasoned through similarly:
type WiderType = { a?: string, b?: string }
type Example = { a: 'a' } & WiderType
declare const example: Example
declare const key: keyof Example
example[key] = 'not a'
//^^^^^^^^^^
// Type '"not a"' is not assignable to type '"a"'.
type WiderType = { [key: string]: string }
type Example = { a: 'a' } & WiderType
declare const example: Example
declare const key: keyof Example
example[key] = 'not a' // no error
In both cases Example carries with it the information that the property a must have a value assignable to 'a' (as can be seen with example.a = 'not a'). But this is not enforced when assigning to dynamic property using a key whose type matches the index signature.
Here's another example which does produce the error I expect:
type WiderType = { [key: string | symbol]: string }
type Example = { [key: string]: 'a' } & WiderType
declare const example: Example
declare const key: string | symbol
example[key] = 'not a' // error, as expected
//^^^^^^^^^^
// Type '"not a"' is not assignable to type '"a"'.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the linked TypeScript Playground examples and compare indexed assignments through string keys with direct property assignments. Trace how the type checker determines the writable type for indexed access, then add coverage showing that narrower declared properties are enforced; done means both reported examples reject "not a" while the existing valid cases remain accepted.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100