You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Possible regression in conditional types using typescript@4.0.2 #40182
typeSelector<T>=(selector: T)=>anytypeValue<TextendsSelector<any>>=ReturnType<T>extendsstring[]
? ReturnType<T>[0][]
: ReturnType<T>extendsstring
? ReturnType<T>[]
: neverfunctionbuildQuery<T=any,SextendsSelector<T>=Selector<T>>(selector: S,values: Value<S>){values.forEach(value=>{// do things with the value})}
Expected behavior:
Using typescript@3.9.5 it used to be the following type (string[] & ReturnType<S>)[0] which can be seen here
Actual behavior:
Using typescript@4.0.2 the type definition changes to an implicit any which can be seen here
Playground Link: See above
Related Issues: I did not find any similar issues.
This is working as expected now - ReturnType<T> where T is a selector will always resolve to any, and any resolves to both conditional type branches, so you end up with array element types (string[] & ReturnType<S>)[0]andstring & ReturnType<S> (realistically, when S is instantiated, these will all collapse to any, but it's not, so it isn't). Practically speaking, we also must consider all branches when looking at constraints while reasoning over generics, any or no. Regardless, these two options mean we have a union of two different array types, meaning values is a union of (array) types, and we're doing .forEach on it. The value parameter type isn't the same across those two overloads, so we type it any (or require a type annotation by issuing an implicit any error with noImplicitAny on).
Even in 3.9.2, you can actually witness the same behavior if you change Selector to return unknown, rather than any (so it doesn't trigger the buggy behavior with any we previously had).
Activity
weswigham commentedon Oct 22, 2020
This is working as expected now -
ReturnType<T>whereTis a selector will always resolve toany, andanyresolves to both conditional type branches, so you end up with array element types(string[] & ReturnType<S>)[0]andstring & ReturnType<S>(realistically, whenSis instantiated, these will all collapse toany, but it's not, so it isn't). Practically speaking, we also must consider all branches when looking at constraints while reasoning over generics,anyor no. Regardless, these two options mean we have a union of two different array types, meaningvaluesis a union of (array) types, and we're doing.forEachon it. Thevalueparameter type isn't the same across those two overloads, so we type itany(or require a type annotation by issuing an implicitanyerror withnoImplicitAnyon).Even in 3.9.2, you can actually witness the same behavior if you change
Selectorto returnunknown, rather thanany(so it doesn't trigger the buggy behavior withanywe previously had).