I have a boolean variable (let’s call it isX
) and two functions (getA
and getB
) that return different types of array:
const isX: boolean; (value unknown at compilation time)
fn getA(): A[];
fn getB(): B[];
The function that is called depends on the boolean variable, following by some common logic that doesn’t depend on type and then finally mapping the elements to components depending on the boolean variable value (either ComponentA or componentB)
const data: A[] | B[] = isX ? getA() : getB();
... custom logic common for both types of elements ...
return data.map(el => isX ? <ComponentA c={el} /> : <ComponentB c={el} />)
Last line gives me the following error:
Type 'A | B' is not assignable to type 'A'.
Type 'B' is missing the following properties from type 'A': x, y, and 3 more.
What would be the best solution to solve this problem?
2
Answers
The error you’re encountering is due to TypeScript’s type checking. Since you’re using conditional logic to determine whether to call
getA()
orgetB()
, TypeScript can’t definitively infer the type ofdata
as eitherA[]
orB[]
, resulting in the type error when you try to map over it.To solve this issue:
By using type assertions (
el as A
andel as B
), you’re telling TypeScript that even thoughdata
might contain elements of typeA | B
, you’re treating them as specific typesA
andB
respectively inside themap
function.While this can be solved by asserting the type (
el as A)
it’s probably not a very good solution.A popular concept for situations like yours is Discriminated Unions. By runtime checking for a property in a Union Type TypeScript can narrow the type to either
A
orB
. Usually one uses a specific property that is available on all types of the union but technically it also works like this:TypeScript Playground