1

The following interface is used to define a JSON API response.
The status field tells whether the request was successful or not.
The data filed is used to set data(only if available) returned by the server upon successful requests.
Similarly the message field is used to set error messages upon failed requests.

export interface IResponse<T> {
    status: 'success' | 'fail';
    data?: T;
    message?: string;
}

Suppose I have the following function that fetches some company data from the server.
The response contains either data or string.

search(keyword: string): Observable<IResponse<ICompany[]|string>> {
   return this.searchCompany(keyword);
}

When I try to call this function as follows, I get a compile error as data could either be ICompany[] or string.

this.dataImportService.search('')
      .subscribe(
        data => {
         data.data[0].company_name // compile error 
      }, err => {
      });

What should I do to get rid of this compile error?

2
  • Can you try data.data[0].company_name? Commented Dec 20, 2017 at 12:39
  • @BunyaminCoskuner sorry, missed that ".data" part. I am getting the compiler error with data.data[0].xxx Commented Dec 20, 2017 at 12:43

2 Answers 2

1

TypeScript compiler has some trouble working with nested property like data.data. The trick is to use a temporary variable const data = data.data. Then the TypeScript compiler behaves as expected: the typeof data === ... type guard is working i.e. the union type ICompany[] | string can be narrowed to ICompany[] or string inside the if (typeof data === ...) block.

Renaming data to response (to be less confusing), we have:

this.dataImportService.search('').subscribe(response => {
    const data = response.data; // inferred type: ICompany[]|string
    if (typeof data !== 'string' && data.length) {
        const firstCompany = data[0]; // inferred type: ICompany
        firstCompany.company_name; // OK
    }
});

Live in the TypeScript Playground

Sign up to request clarification or add additional context in comments.

Comments

1

If you want to get rid of the compile error you could use <any> to avoid type checking.

this.dataImportService.search('')
      .subscribe(
        (data: any) => { // <- here
         data.data[0].company_name // compile error 
      }, err => {
});

But really you should not do that. Typescript is just warning you that if your search method returns a string you will have an error or at least unexpected behavior.

Say search return 'hoho or whatever', data.data will be 'hoho or whatever' data.data[0] = 'h'; data.data[0].company_name will be undefined.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.