You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// A *self-contained* demonstration of the problem follows...functionf<T,KextendskeyofT>(obj: T,k: K,value:T[K]){for(letkeyinobj){value=obj[key];break;}returnvalue;}f({x: 1,y: ""},'y',"1").charAt(0);//runtime error
Expected behavior:
Compiler error Actual behavior:
Runtime error
It looks like TS is interpreting T[K] where K extends keyof T to be something like T[keyof T], i.e., the union of all values of properties of T. And so it allows any value assignable to T[keyof T] to a variable of type T[K], even when that could lead to runtime errors.
Another instance of this:
interfaceFoo{s: string;n: number;}functiong<KextendskeyofFoo>(){varindexed: Foo[K]='what';// no error? what if K is 'n'?}
I doubt this is intended. It seems like a design limitation, if not a bug.
Joe Calzaretta (@jcalz) I am also in doubt about this, because there is no specification for this case all I can is to pretend it to be a bug)
But my thoughts about this case are other.
TypeScript can infer type for value as string, but type of obj[key] maybe union of all T[K] types therefore we can't assign union of type to it's constituent. But it is a assumption.
ghost changed the title [-]Lookup type inside "for in" loop[/-][+]T[keyof T] assignable to T[K][/+]on Jul 13, 2017
Joe Calzaretta (@jcalz) your repro exposes a design limitation; if we distinguished the types of read locations and write locations then we could say that the type of Foo[K] is string | number when reading and string & number when writing.
However, read/write distinction is similar to variance handling, so we are unlikely to add one set of features without the other. And that set of features is very complex, both to use and to implement, so I don't think it will happen soon, if at all.
Activity
jcalz commentedon Jul 13, 2017
It looks like TS is interpreting
T[K]whereK extends keyof Tto be something likeT[keyof T], i.e., the union of all values of properties ofT. And so it allows any value assignable toT[keyof T]to a variable of typeT[K], even when that could lead to runtime errors.Another instance of this:
I doubt this is intended. It seems like a design limitation, if not a bug.
olegdunkan commentedon Jul 13, 2017
Joe Calzaretta (@jcalz) I am also in doubt about this, because there is no specification for this case all I can is to pretend it to be a bug)
But my thoughts about this case are other.
TypeScript can infer type for
valueasstring, but type ofobj[key]maybe union of allT[K]types therefore we can't assign union of type to it's constituent. But it is a assumption.[-]Lookup type inside "for in" loop[/-][+]T[keyof T] assignable to T[K][/+]sandersn commentedon Aug 28, 2017
olegdunkan the fix for your bug is up at #17912.
Joe Calzaretta (@jcalz) your repro exposes a design limitation; if we distinguished the types of read locations and write locations then we could say that the type of
Foo[K]isstring | numberwhen reading andstring & numberwhen writing.However, read/write distinction is similar to variance handling, so we are unlikely to add one set of features without the other. And that set of features is very complex, both to use and to implement, so I don't think it will happen soon, if at all.