Reputation: 477
Typescript compiler
keeps throwing error when I try to use union or multiple types / interfaces.
My requirement
From the server I receive an object as response in which one key ('errorMessages') has data type string[]
and the other key ('data') can either be an object
or an array
. I wrote an interface
for this which should look like below:
interface MyServerResponse {
errorMessages: string[];
data: {
headers: string[];
body: any[][];
} | any[]>;
}
Received compiler error on trying to access 'headers'
Property 'headers' does not exist on type 'any[] | { headers: string[]; body: any[][]; }'
Isn't it possible to implement this using union just like for number | boolean
, string | null
, etc.?
Upvotes: 2
Views: 10214
Reputation: 1765
To inform TypeScript which of interfaces you expect you can just cast variable in this specific function:
interface dataTypeResponse {
headers: string[];
body: any[][];
}
interface MyServerResponse {
errorMessages: string[];
data: dataTypeResponse | any[];
}
doTheMagic(d: MyServerResponse) {
// access it like this:
const headers = (<dataTypeResponse>d.data).headers;
}
Upvotes: 3
Reputation: 114695
When you have a type union you can only access members that are common to all types. If you want to say it's one or the other you need a type guard to let the compiler know that it's of the right type:
// this type isn't needed but it makes the code more readable
type headersBody = { headers: string[]; body: any[][] };
function isHeadersBody(obj: headersBody | any[]): obj is headersBody {
return !Array.isArray(obj);
// or better yet
// return Array.isArray(obj["headers"]) && Array.isArray(obj["body"]);
}
let obj: headersBody | any[];
if (isHeadersBody(obj)) {
console.log(obj.body.length);
}
Upvotes: 5
Reputation: 455
Typescript - Advanced Types says
If we have a value that has a union type, we can only access members that are common to all types in the union.
So you are getting the error because "headers" isn't common across the types in the union.
Upvotes: 3