Repository navigation
.map() .reduce() .filter() methods fail with "This expression is not callable." error on valid array with union type #36390
Description
Activity
- changed the title
[-]Union type of arrays fails on .map() .reduce() .filter() methods with "This expression is not callable."[/-][+] .map() .reduce() .filter() methods fail with "This expression is not callable." error on valid array with union type[/+]on Jan 24, 2020 DanielRosenwasser commented
on Jan 24, 2020 MemberMore actionsI think this is a duplicate of #7294
Reacted by Joe CalzarettaDuplicate of #7294 (see comment). Related to #29011.
Mentioned in documentation as caveats for improved behavior for calling union types:
This new behavior only kicks in when at most one type in the union has multiple overloads, and at most one type in the union has a generic signature. That means methods on
number[] | string[]likemap(which is generic) still won’t be callable.Is this really a duplicate? The 'duplicate' issue is marked as closed, but this issue still exists. If it really is a duplicate, can we re-open #7294 to handle this case?
Reacted by Ali-Khamis, Patrick Wang, Vas Sudanagunta and Christian Toneydragomirtitian commented
on Feb 12, 2020 ContributorMore actionsThe reason stated by Wesley Wigham (@weswigham) for not unifying for generic signatures with multiple signatures is that:
Well, it's because we don't really know if the generics are the same (and so because of that we'd opt to make the parameter type T & T' instead and combine the type parameter lists to <T, T'>), so we opt to not allow the call.
But for function signatures originating from the same declaration we can be sure that we are talking about the same overload signatures in the same order and with the same generic parameters. As long as the generics don't have constraints, unifying the signatures should be safe IMO.
I think that unifying for this case would satisfy a lot of use cases.
ArrayandPromisewould benefit from this and those are the usual place people run into this limitation.Yeah, I have a change around here somewhere that allows it for exactly that situation rummages through bin of old PRs
dragomirtitian commented
on Feb 12, 2020 ContributorMore actionsWesley Wigham (@weswigham) What was wrong with it? Why did it get stuck ? Can we revive it :D ?
#31023 contains the relevant code. It's a bit old, and some parts of it are probably no longer needed thanks to some other signature resolution changes we made (namely the base signature stuff should no longer be needed).
Reacted by Titian Cernicova-Dragomir and Erindragomirtitian commented
on Feb 12, 2020 ContributorMore actionsCool! So is this planned for a release in the future I'm guessing? I wanted to have a look at this over the weekend but glad to see it already there and we will get eventually :)
- addedExperience EnhancementNoncontroversial enhancementsNoncontroversial enhancementsSuggestionAn idea for TypeScriptAn idea for TypeScript
on Feb 21, 2020 Looks like my issue #36307 talks about pretty much the same behavior, linking for discoverability. Glad to see there's been some movement!
Until this gets fix you can do something like:
const arr: number[] | string[] = []; // Add as any[] (arr as any[]).map((a: number | string, index: number) => { return index });Reacted by Andriy Fedorchenko, Shujath Khan, Bruno Pontes, Jaehoon Yang, Lucas Bueno, humkins, Haltarys, Ahmad Haider, Tim Haywood, ziga and 16 moreReacted by Alexander Vetchinkin and 4000degrees9 remaining items
This issue is closed, but the
reduce()example persists:const arr: number[] | string[] = []; arr.reduce((acc: Array<string>, a: number | string, index: number) => { return [] }, []) /* This expression is not callable. Each member of the union type '...' has signatures, but none of those signatures are compatible with each other. */
Reacted by Joel, Fernando Barros, Ian Martorell, Rémy Machado, Alex Nguyen, Tim Martin, Kay Wolf, matrs and Leonardo GabrielI'm super excited about the improvements in #31023! But it doesn't seem to have completely resolved the issues with calling array methods on unions of arrays.
I tested a few common array methods and found the following results:
- .map() works
- .forEach() works
- .includes() works
- .indexOf() works
- .findIndex() works
- .some() works
- .every() does not work
- .filter() does not work
- .find() does not work
- .reduce() known not working (issue)
I've created a new issue to track the remaining functionality.
Reacted by Jacek Nowacki, Petr Odut, Daniel Skogly, andreas, Bartosz, Sulaiman Adewale, Zoey Truong, Joel, Vas Sudanagunta, Alex Ivanov and 4 moreis this getting fixed anytime soon ?
Reacted by David Nyhuis, Rachel Leggett and Louis Lora-RoncoI'm super excited about the improvements in #31023! But it doesn't seem to have completely resolved the issues with calling array methods on unions of arrays.
I tested a few common array methods and found the following results:
- .map() works
- .forEach() works
- .includes() works
- .indexOf() works
- .findIndex() works
- .some() works
- .every() does not work
- .filter() does not work
- .find() does not work
- .reduce() known not working (issue)
I've created a new issue to track the remaining functionality.
Alex Ryan (@ialexryan) What typescript version does this fix go out?
We're on the latest Typescript and bumped into this. Do you know when it's going out? Ryan Cavanaugh (@RyanCavanaugh)
Reacted by Joel, Jordin, Fumarie, Rémy Machado, Jake V, JF and CoderDixI just bumped into the same issue
Reacted by Joel, Zakariae Filali, Abhilash Nayak, Fernando Donaire, Rich Selfridge, Jordin, Teresito, Fumarie, cmoldo, qingting and 35 moreHow is this issue closed?
.filter() and .find() is still not working as of 4.9.5..Reacted by Quan VoI think #44373 is the open issue about this
Thanks, didn't see that.. :)
I just bumped into the same issue too
TypeScript Version: any
Code:
Expected behavior: TS should let me iterate through array (I tell it the type is either array of numbers OR array of strings (not an array of mixed types). In any case the variable is an array and those methods should be callable.
Actual behavior: TS throws error "This expression is not callable."