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
Narrowing does not work for constrained template arguments in JS #38309
/** * @template {string | string[]} T * @param {T} a */functionfoo(a){if(Array.isArray(a)){a.map;// somewhat correctly narrowed to (T & any[])}else{a.substr;// Error, not narrowed at all (T)}}
Expected behavior:
in the if-branch, a is narrowed to string[]
in the else-branch, a is narrowed to string
Actual behavior:
in the if-branch, a is narrowed to T & any[]
in the else-branch, a is NOT narrowed
Playground Link: This is JS, so the playground doesn't work
Related Issues: Constraint support was added in #24600
🤷♀️ We certainly don't today. (Generics are never narrowed in the false condition.) I'd normally say that something like #29317 would allow us to fix this (since we would pretty trivially say T & not string[] in the false branch, which is more accurate, which can then go on to filter the constraint when fetched). Specifically in cases like this, where we're guarding against an element of a union constraint, filtering the constraint and intersecting it may work as a substitute for that... Unfortunately, specifically for Array, Array.isArray now has a return signature type of arg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[], which is decidedly not "exactly an element of a union constraint", so it's.... unclear that we could adjust this without a full negated-type-style fix.
Activity
IllusionMH commentedon May 4, 2020
It's not only in JS.
TS nightly repro
AlCalzone commentedon May 7, 2020
You're right. That is probably intended then, but at the very least it is not intuitive...
RyanCavanaugh commentedon Jun 5, 2020
Anders Hejlsberg (@ahejlsberg) Wesley Wigham (@weswigham) should we be narrowing to
T & stringin theelse?weswigham commentedon Oct 22, 2020
🤷♀️ We certainly don't today. (Generics are never narrowed in the
falsecondition.) I'd normally say that something like #29317 would allow us to fix this (since we would pretty trivially sayT & not string[]in the false branch, which is more accurate, which can then go on to filter the constraint when fetched). Specifically in cases like this, where we're guarding against an element of a union constraint, filtering the constraint and intersecting it may work as a substitute for that... Unfortunately, specifically forArray,Array.isArraynow has a return signature type ofarg is T extends readonly any[] ? unknown extends T ? never : readonly any[] : any[], which is decidedly not "exactly an element of a union constraint", so it's.... unclear that we could adjust this without a full negated-type-style fix.6 remaining items
n9 commentedon Jun 8, 2021
Is this issue also cause for the following error?
TS Play
Or the cause is different?