I have the following structure:
interface Test1 {
number: number;
}
interface Test2 extends Test1 {
text: string;
}
let test: Test1[] | Test2[] = [];
test.map(obj => {}); // does not work
I am getting the error:
Cannot invoke an expression whose type lacks a call signature. Type '{ (this: [Test1, Test1, Test1, Test1, Test1], callbackfn: (this: void, value: Test1, index: nu...' has no compatible call signatures
How can I map
over the test variable?
Edit for 4.2
map
has become callable now, but you still need an explicit type annotation on its argument to get it to work as expected (the type parameter is no contextually typed)
let test: Test1[] | Test2[] = [];
test.map((obj: Test1 | Test2) => {});
Playground Link
This situation is likely to improve in future versions making this answer mostly obsolete (see PR that will correctly synthesize contextual types for parameters)
Original answer pre 4.2
The problem is that for union types, members which are functions will also be typed as union types, so the type of map
will be (<U>(callbackfn: (value: Test1, index: number, array: Test1[]) => U, thisArg?: any) => U[]) | (<U>(callbackfn: (value: Test2, index: number, array: Test2[]) => U)
Which as far as typescript is concerned is not callable.
You can either declare an array of the union of Test1
and Test2
let test: (Test1 | Test2)[] = [];
test.map(obj => {});
Or you can use a type assertion when you make the call:
let test: Test1[] | Test2[] = [];
(test as Array<Test1|Test2>).map(o=> {});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With