James Antony
James Antony

Reputation: 477

Typescript union of Array and Object types

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

Answers (3)

Baumi
Baumi

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

Motti
Motti

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

DaveG
DaveG

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

Related Questions