Skip to content

Unable to unify different uses of same conditional type #23541

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

Closed
leighman opened this issue Apr 19, 2018 · 3 comments
Closed

Unable to unify different uses of same conditional type #23541

leighman opened this issue Apr 19, 2018 · 3 comments
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed

Comments

@leighman
Copy link

leighman commented Apr 19, 2018

TypeScript Version: 2.8.1

Search Terms:
conditional type

Code

const a: TypeFromOption<"configurationA"> = {data: "test"}

const b: TypeFromOption<"configurationB"> = {data: 1}

interface Whatever<T> {
  data: T
}

type Options = "configurationA" | "configurationB"

type TypeFromOption<T extends Options> =
  T extends "configurationA" ? Whatever<string> :
  T extends "configurationB" ? Whatever<number> :
  never

const createThing = <T extends Options>(type: T): TypeFromOption<T> => {
  switch (type) {
    case "configurationA":
      return a
    case "configurationB":
      return b
  }
}

Expected behavior:

I would expect that typescript should be able to infer that the return type of each case in the switch statement is consistent with what the conditional type returns for the given T

Actual behavior:

Type 'Whatever<string>' is not assignable to type 'TypeFromOption<T>'
Type 'Whatever<number>' is not assignable to type 'TypeFromOption<T>'

Adding as any after return a and return b causes it to work as expected and infer the correct return type for the function.

Playground Link:
http://www.typescriptlang.org/play/#src=const%20a%3A%20TypeFromOption<"configurationA">%20%3D%20%7Bdata%3A%20"test"%7D%0D%0A%0D%0Aconst%20b%3A%20TypeFromOption<"configurationB">%20%3D%20%7Bdata%3A%201%7D%0D%0A%0D%0Ainterface%20Whatever%20%7B%0D%0A%20%20data%3A%20T%0D%0A%7D%0D%0A%0D%0Atype%20Options%20%3D%20"configurationA"%20%7C%20"configurationB"%0D%0A%0D%0Atype%20TypeFromOption<T%20extends%20Options>%20%3D%0D%0A%20%20T%20extends%20"configurationA"%20%3F%20Whatever%20%3A%0D%0A%20%20T%20extends%20"configurationB"%20%3F%20Whatever%20%3A%0D%0A%20%20never%0D%0A%0D%0Aconst%20createThing%20%3D%20<T%20extends%20Options>(type%3A%20T)%3A%20TypeFromOption%20%3D>%20%7B%0D%0A%20%20switch%20(type)%20%7B%0D%0A%20%20%20%20case%20"configurationA"%3A%0D%0A%20%20%20%20%20%20return%20a%0D%0A%20%20%20%20case%20"configurationB"%3A%0D%0A%20%20%20%20%20%20return%20b%0D%0A%20%20%7D%0D%0A%7D

Related Issues:

@RyanCavanaugh RyanCavanaugh added the Design Limitation Constraints of the existing architecture prevent this from being fixed label Apr 19, 2018
@RyanCavanaugh
Copy link
Member

Union-constrained generics aren't narrowed, so we don't change the type of type in the switch and don't have any chance to even realize the return statements refer to different cases. I'm not sure there's any concrete next step we could do to fix this - in general we cannot reason very strongly about a type parameter because we can't reason about a domain that doesn't exist yet, though literal-union-constrained generics might be a special case. But there's no mechanism in place right now to unify the flow control behavior with the conditional types - without more scenarios I think this is pretty far out of scope.

#23132 might be related

@leighman
Copy link
Author

Yeh, thought typescript might be able to do more because it was a union of literals.
Thanks for the info.

@typescript-bot
Copy link
Collaborator

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

@microsoft microsoft locked and limited conversation to collaborators Jul 31, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed
Projects
None yet
Development

No branches or pull requests

3 participants