Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Function can return wrong values despite type #30603

Closed
bjornua opened this issue Mar 26, 2019 · 5 comments · Fixed by #30769
Closed

Function can return wrong values despite type #30603

bjornua opened this issue Mar 26, 2019 · 5 comments · Fixed by #30769
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed Fixed A PR has been merged for this issue

Comments

@bjornua
Copy link

bjornua commented Mar 26, 2019

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

@RyanCavanaugh RyanCavanaugh added Bug A bug in TypeScript and removed Bug A bug in TypeScript labels Mar 26, 2019
@jack-williams
Copy link
Collaborator

jack-williams commented Mar 27, 2019

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"
  • and 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.

@jack-williams
Copy link
Collaborator

See this comment by Anders for (much) more detail.

@DanielRosenwasser
Copy link
Member

Feels bad - but does that mean we should mark this as a duplicate @ahejlsberg?

@RyanCavanaugh RyanCavanaugh added the Design Limitation Constraints of the existing architecture prevent this from being fixed label Mar 27, 2019
@jack-williams
Copy link
Collaborator

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.

@ahejlsberg
Copy link
Member

@jack-williams I'll give it a try.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed Fixed A PR has been merged for this issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants