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

Incorrect type inference from parameter contraint in conditional types #22221

Closed
s-ve opened this issue Feb 28, 2018 · 4 comments
Closed

Incorrect type inference from parameter contraint in conditional types #22221

s-ve opened this issue Feb 28, 2018 · 4 comments
Assignees
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue

Comments

@s-ve
Copy link

s-ve commented Feb 28, 2018

TypeScript Version:
2.8.0-dev.201802213

Search Terms:
conditional, inference, constraint

Code

type MustBeString<T extends string> = T;
type EnsureIsString<T> = T extends MustBeString<infer U> ? U : never;

type Test1 = EnsureIsString<'hello'>; //'hello'
type Test2 = EnsureIsString<42>; //42

Expected behavior:
Test2 has type never

Actual behavior:
Test2 has type 42, even though typescript correctly infers that U must be a string in the conditional true branch.

Playground Link:
Related issues:
#21937 #21631

@jcalz
Copy link
Contributor

jcalz commented Feb 28, 2018

Related to #21937? (Please note that the issue template does ask you for search terms and related issues)

@s-ve
Copy link
Author

s-ve commented Feb 28, 2018

@jcalz I just updated my issue to match the template

@mhegazy
Copy link
Contributor

mhegazy commented Mar 3, 2018

The constraint failure does not invalidate the inference really. do you have a use case where this is needed?

@s-ve
Copy link
Author

s-ve commented Mar 3, 2018

@mhegazy

What motivated me to report this is the fact that this construct can make Typescript ignore type constraints :

type A<T extends string> = {
  [TKey in T]: string
};

type B<T extends string> = T;
type C<T> = T extends B<infer U> ? A<U> : never;
type D = C<boolean>; // Evaluated as A<boolean>, which shouldn't be valid

it also seems inconsistent to me since this code works as expected :

type B<T extends string> = {a: T};
type C<T> = T extends B<infer U> ? A<U> : never;
type D = C<{a: boolean}>; // never, as expected

I don't know if it can be a problem in real world code though... I can't think of any use-case where an "Identity" type such as B would be useful in a conditional type...

EDIT
Please ignore the second part of my comment, the result is exactly the same (A<boolean>, not never). This had nothing to do with the fact that B is a "identity" type. Sorry about that.

@ahejlsberg ahejlsberg self-assigned this Mar 5, 2018
@ahejlsberg ahejlsberg added the Bug A bug in TypeScript label Mar 5, 2018
@ahejlsberg ahejlsberg added this to the TypeScript 2.8 milestone Mar 5, 2018
@ahejlsberg ahejlsberg added the Fixed A PR has been merged for this issue label Mar 5, 2018
@microsoft microsoft locked and limited conversation to collaborators Jul 25, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue
Projects
None yet
Development

No branches or pull requests

4 participants