question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Wrong branch on conditional type with ReturnType of T condition

See original GitHub issue

I think I found a bug.

Last non-broken TS version for this is 3.1.6 on typescript playground. All later versions are broken.

Which gets me thinking: is this maybe intended behavior because it is “broken” for so many versions?

But i dont know why it should NOT be a bug. Either way if it’s indeed not a bug, i need some serious brain rewiring from you guys please, because cant wrap my head around this behavior…

Let’s get started

TypeScript Version: Nightly, all the way down to and including 3.3.3, tested with all these versions on playground

Search Terms: conditional types return type

Code

type StringOrNumber<T extends () => any> = [ReturnType<T>] extends [string]
  ? string
  : number;

type Test = StringOrNumber<() => number>; // oh noes, "string"

Expected behavior: I expect number. Because [number] just cannot extend [string]

The TS handbook talks about deferred evaluation of conditional types. I seems it is not working here!! Evaluation of “ReturnType<T>” should be deferred until the type is actually used in a concrete way!

Actual behavior: The conditional type evaluates to string no matter what function type is passed in

type StringOrNumber2<T extends () => number> = [ReturnType<T>] extends [string]
  ? string
  : number;

type Test2 = StringOrNumber2<() => number>; // oh noes, "string"

Expected behavior: I expect number, even the generic constaint now demands it!

Actual behavior: Again, always get “string”

type StringOrNumber3<T extends () => number> = [number] extends [string]
  ? string
  : number;

type Test3 = StringOrNumber3<() => number>; // correct, number

This is just for show, I expect number and get number, only difference is I now hardcode “number” instead of “ReturnType<T>”

Playground Link: https://www.typescriptlang.org/play/?ts=Nightly#code/FAkFwTwBwUwAgMpgE4EsB2BzA8sgcgK4C2ARjMgDwAqcMAHmDOgCYDOcAFAJRwC8AfHACG6CIN5wA2gCUYYAsnRVoMavwC6tBkzZTWKDJnXA4cAPxx9aLCbgAuOOmJlkAbnAq4VGPr6IDWLiEpOQU3HyCTiHI-K5wAPTxcAD2ABaOyT4ANHAARFaGuaDAkLD+1jj4zuQATNRajCzs4QKO1TF+MnIKSipqmvSNupIFWMamFqOYtg5RLu4lnt76NX5IFUHtdS2R7bEJSWkZ2XlTRaCl8OuGm9EAzPWDOs08rXPk4lLvyAPaTXoBIy2SaAmZtaILS5eHxgO5rQG3FwPHbglz7RJwADGyWQyBgmLAOW+xRJQA

Related Issues: no, searched the issues

Issue Analytics

  • State:open
  • Created 3 years ago
  • Comments:8 (7 by maintainers)

github_iconTop GitHub Comments

3reactions
RyanCavanaughcommented, Jul 1, 2020

Normally this is where I say “Ah, here’s the subtle thing you missed”, but… yeah that seems totally broken and I don’t understand how it’s been that way for so long without anyone else noticing?

1reaction
ahejlsbergcommented, Nov 21, 2020

@jcalz Decided to put up a separate PR for that issue: #41622.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Documentation - Conditional Types - TypeScript
Conditional types help describe the relation between the types of inputs and ... otherwise you'll get the type in the latter branch (the...
Read more >
typescript - Conditional type not narrowed in false branch - Stack ...
So the obvious next action is to reverse the condition. But for some reason, TypeScript isn't able to narrow the false branch of...
Read more >
The guide to conditional types in TypeScript - LogRocket Blog
Conditional types can be recursive; that is, one, or both, of the branches can themselves be a conditional type: type Recursive<T> = T...
Read more >
Understanding Conditional Types in TypeScript - Syncfusion
Conditional types allow developers to decide the type of a certain variable or the method's return type based on a condition.
Read more >
Conditional Types in TypeScript - Marius Schulz
T , U , X , and Y stand for arbitrary types. The T extends U part describes the type relationship test. If...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found