TypeScript Version: 3.4.0-dev.20190326
Search Terms: Function Generic Extends Keyof Property
Code
interface Type {
a: 123;
b: "some string";
}
function get123<K extends keyof Type>(): Type[K] {
return 123;
}
Expected behavior:
The function get123 would yield an error as the return type might not be correct as it depends on K.
Actual behavior:
No error for get123. That function would obviously always return 123.
Playground Link: Example on TypeScript Playground
I think this is an unsoundness that exists to support index access types on this. The assignability rules for Type[K] are defined as:
// A type S is related to a type T[K], where T and K aren't both type variables, if S is related to C,
// where C is the base constraint of T[K]
The base constraint of Type[K] is the type you get when indexing into Type using the base constraint of K which is "a" | "b". So the checker sees that 123 is assignable to Type[K] as:
123 is assignable to 123 | "some string"Type[K] ==> Type["a" | "b"] ==> 123 | "some string"The way to prevent the unsoundness would be to write it using two variables, though I'm not sure this actually solves your problem.
function get123<K extends keyof Type, T extends Type = Type>(): T[K] {
return 123;
}
EDIT: Just to add the caveat that I think this is what it's doing, and why, but nothing I say is official or guaranteed to be correct.
See this comment by Anders for (much) more detail.
Feels bad - but does that mean we should mark this as a duplicate @ahejlsberg?
Would it be too much to restrict the unsoundness to cases where the object type is generic, but the key type is concrete? This example would be the converse and use the sound path.
@jack-williams I'll give it a try.
Most helpful comment
@jack-williams I'll give it a try.