Update 2019-03: With the release of TypeScript 3.3, there has there has been progress for calling a union of function types, but unfortunately this pain point still exists for generic methods like Array.prototype.map()
:
This is a pain point in TypeScript: there's no way to call a "union of function types" unless either they accept exactly the same arguments, or starting in TS3.3, if at most one element of the union of functions is generic or overloaded. In your case, since category
is Cat1[] | Cat2[] | Cat3[]
, the method category.map()
is itself a union of generic functions whose parameters are not the same; and you can't call that. It should be safe to call category.map(f)
if f
is a function which accepts Cat1 | Cat2 | Cat3
(this may seem obvious, but involves understanding contravariance of method arguments, which is easy to get mixed up). But, as the linked issue mentions, the compiler doesn't let you do that:
This is currently by design because we don't synthesize an intersectional call signature when getting the members of a union type -- only call signatures which are identical appear on the unioned type.
So you get an error. Luckily there are workarounds. The easiest in your case is to treat category
not as Cat1[] | Cat2[] | Cat3[]
, but as (Cat1 | Cat2 | Cat3)[]
. As long as you're just reading from the array and not writing to it, it should be safe to do that:
let category: Cat1[] | Cat2[] | Cat3[] = this.getCategory();
const mappableCategory = category as (Cat1 | Cat2 | Cat3)[];
Now you should be able to map over mappableCategory
instead of category
:
mappableCategory.map((item: any) => { /* ... */ }); // should work now.
(Just to reiterate: reading from mappableCategory
is fine, but writing to mappableCategory
could be a mistake, since it will happily accept elements of Cat1
, even if the underlying category
was an array of Cat2
. So don't write to it unless you're sure what you're doing.)
Hope that helps you. Good luck!
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…