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

3.4.0-rc - behaviour changed from 3.3 (regression?) #30489

Closed
xaviergonz opened this issue Mar 19, 2019 · 5 comments · Fixed by #30592
Closed

3.4.0-rc - behaviour changed from 3.3 (regression?) #30489

xaviergonz opened this issue Mar 19, 2019 · 5 comments · Fixed by #30592
Labels
Experience Enhancement Noncontroversial enhancements Suggestion An idea for TypeScript

Comments

@xaviergonz
Copy link

I found a case where types yielded differ between 3.3 and 3.4, but I'm not sure if it is a regression or it is intended

interface I<T> {
    a: T
}

// this is different between 3.3 and 3.4
type O<T> = T extends I<any> ? T : never
type B = O<I<number>> // I<number> in TS3.3, I<any> & I<number> in TS3.4 (which boils down to I<any>

// this however is the same
type O2<T> = T extends I<infer _> ? T : never
type B2 = O2<I<number>> // I<number> in both
@xaviergonz xaviergonz changed the title 3.4 - behaviour changed from 3.3 (regression?) 3.4.0-rc - behaviour changed from 3.3 (regression?) Mar 19, 2019
@jack-williams
Copy link
Collaborator

This is caused by #29437 I think. Not sure I would class this as a regression: is it causing negative behaviour?

@xaviergonz
Copy link
Author

xaviergonz commented Mar 19, 2019

At least for me :) , I use it like this

type ExtendIfI1<T> = T extends I1<any> ? T & Something : T

I can't use T extends I1<infer X> ? I1<X> & Something : T since if I1 had more stuff than I1 it would be lost, and having to write infer on the left for it to work was hard to find out

I think it boils down to the generic being inside the template part, this is

type A<T> = T extends any ? T : never
type B = A<number> // this is any & number, which is number

type O<T> = T extends I<any> ? T : never
type B = O<I<number>>
// could this be changed so it generates I<any & number>, which is I<number>
// rather than I<any> & I<number> ?

@RyanCavanaugh
Copy link
Member

RyanCavanaugh commented Mar 19, 2019

This is the intended behavior to improve inference elsewhere by "collapsing" conditional types into plain types when we detect that's possible.

One option is to use

type O<T> = T extends I<unknown> ? T : never

This will produce the type I<unknown> & I<number> which is indistinguishable from I<number> but also a little ugly.

You can also make the conditional non-distributive by writing

type O<T> = [T] extends [I<unknown>] ? T : never

@RyanCavanaugh RyanCavanaugh added the Working as Intended The behavior described is the intended behavior; this is not a bug label Mar 19, 2019
@typescript-bot
Copy link
Collaborator

This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@weswigham
Copy link
Member

While the original behavior was intended, its interaction with any is undesirable - to reduce breakage and make better output types, in #30592 we introduce supertype reduction on substitution type instantiation, which should eliminate needless any'd up intersection members in most cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Experience Enhancement Noncontroversial enhancements Suggestion An idea for TypeScript
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants