String index into a generic type having a string index signature isn't assignable to indexed access type
See original GitHub issueBug Report
🔎 Search Terms
string index signature; indexed access; generic; 2322; not assignable
🕗 Version & Regression Information
This seems to be there all the way back to TS3.5, maybe introduced by #30769, although I’m not sure I understand why.
-This changed between versions 3.3.3 and 3.5.1
⏯ Playground Link
Playground link with relevant code
💻 Code
interface Foo {
a: { [k: string]: string | undefined };
b: { [k: string]: number | undefined };
c: { [k: string]: boolean | undefined };
}
function get<K extends keyof Foo>(foo: Foo, k: K, x: string): Foo[K][string] {
return foo[k][x]; // error!
// Type 'string | number | boolean | undefined' is not assignable to type 'Foo[K][string]'.
}
🙁 Actual behavior
Reading a property with a string
key from a Foo[K]
object does not produce a value of type Foo[K][string]
, even in a non-widening position.
🙂 Expected behavior
Indexing into a Foo[K]
value with a string
key should produce a property of type Foo[K][string]
if such a type is in a non-widening position.
This might be similar to #31661 and #33181 but I can’t tell.
Note that numeric index signatures work as expected:
interface Foo {
a: { [k: number]: string | undefined };
b: { [k: number]: number | undefined };
c: { [k: number]: boolean | undefined };
}
function get<K extends keyof Foo>(foo: Foo, k: K, x: number): Foo[K][number] {
return foo[k][x]; // okay
}
And known literal keys work as expected:
interface Foo {
a: { x: string | undefined };
b: { x: number | undefined };
c: { x: boolean | undefined };
}
function get<K extends keyof Foo>(foo: Foo, k: K, x: "x"): Foo[K]["x"] {
return foo[k][x]; // okay
}
But string index signatures (and symbol also) fail for some reason.
This can be worked around easily enough:
function get<K extends keyof Foo>(foo: Foo, k: K, x: keyof Foo[K]): Foo[K][keyof Foo[K]] {
return foo[k][x]; // okay
}
But I’m wondering what’s going on.
Playground link with above examples
(note to self: go back to this SO answer if I acquire more cluefulness here)
Issue Analytics
- State:
- Created a year ago
- Reactions:1
- Comments:5 (4 by maintainers)
Top GitHub Comments
That’s a widening, the same as you’d see in
m
here:Okay, then I guess I meant “in a non-widening position” instead of “contextually” or something. Unless that’s wrong too.