6

I have a promise, that I use in order to setState, when I fetch Data for a specific User. Below is the code for that:

getUserUsername = (): string => {
    const { match } = this.props;
    return match.params.username;
  };

  onFetchUser = () =>
    getUser(this.getUserUsername())
      .then(username => {
        if (this.hasBeenMounted) {
          this.setState({
            user: username.data // The error is here.
          });
        }
      })
      .catch((errorResponse: HttpResponseObj | null = null) => {
        if (this.hasBeenMounted) {
          this.setState({
            isLoading: false,
            user: null,
            errorMessage: errorResponse
          });
        }
      });

But I get this TS error saying:

Property 'data' does not exist on type 'void | AxiosResponse<IUser>'.
  Property 'data' does not exist on type 'void'.ts(2339)
---
any

The getUser(), is a service that I use and the code for it is here:

export const getUser = (username: string, initialOptions = {}): HttpResponse<IUser> => {
  const options = {
    method: httpMethod.GET,
    url: endpoint.GET_USER(username)
  };
  return Instance(options, lensesOptions);
};

The code for the HttpResponse is here:

export interface HttpResponse<T> extends Promise<void | AxiosResponse<T>> {}

I tried something like:

      .then((username): HttpResponse<any> => { // Doesn't work though
        if (this.hasBeenMounted) {
          this.setState({
            user: username.data
          });
        }
      })

Here is the Axios Interface:

export interface AxiosResponse<T = any>  {
  data: T;
  status: number;
  statusText: string;
  headers: any;
  config: AxiosRequestConfig;
  request?: any;
}

Can you please explain to me what is the problem. I go to axios Interface and I see it data, as well as the generic there no problem.. Thank you!!

chazsolo
  • 7,873
  • 1
  • 20
  • 44

1 Answers1

8

You have to check the type of username before try to use it because the function is returning two values with different properties (void and AxiosResponse)

So you have to check like this:

  .then(username => {
    // Check if it is not void
    if (this.hasBeenMounted && username ) { 
      this.setState({
        user: username.data
      });
    }
  })
SnakeDrak
  • 3,406
  • 4
  • 28
  • 41
  • Ok, both of them worked. One question though. Is there any difference between, the existing answer and the one you posted before. `username !== undefined && username.data` !== `typeof username !== 'undefined'`. –  Mar 26 '19 at 14:44
  • 1
    See my latest update. Username could be `null` or `undefined` because `void` is a [supertype](https://www.typescriptlang.org/docs/handbook/basic-types.html#void) of them. So, if you just check the username value [it evaluates `null` and `undefined`](https://stackoverflow.com/a/44017547/2389232) among others. Don't use my previous answer (`typeof username !== 'undefined'`) because I took advantage of a possible typescript bug. I have created a [question to understand it](https://stackoverflow.com/questions/55360626/typescript-property-property-does-not-exist-on-type-void-isample). – SnakeDrak Mar 26 '19 at 15:42