Flow(InferError): Cannot call await with 'axios.get(...)' bound to 'p'

Viewed 1227

I'm getting some Flow errors using axios.

Cannot call await with 'axios.get(...)' bound to 'p' because:
Either property 'error_message' is missing in 'AxiosXHR'. 
Or property 'data' is missing in 'Promise'

Here is my code, with an attempted type annotation. (Same error without the AxiosPromise<Object> annotation.) The error is on axios.get(url).

  async handleAddressChange(): AxiosPromise<Object> {
    const url = `https://maps.googleapis.com/maps/api/place/autocomplete/json?key=${GoogleMapsApiKey}&input=${this.state.address}`;
    try {
      const { data, error_message } = await axios.get(url);
      if (error_message) throw Error(error_message);
      this.setState({
        addressPredictions: data.predictions,
        showPredictions: true
      });
    } catch (err) {
      console.warn(err);
    }
  }

Funny thing is that in another file axios gives no Flow problems:

export async function loginWithApi(creds: AuthParams) {
  const res = await axios.get(ApiUrls.login, { params: creds });
  return res.data;
}

I have import type { AxiosPromise, $AxiosXHR } from "axios"; in my file.

Anyone know how to fix this?

1 Answers

In case of error there will be no error_message in returned payload, but the error goes into the catch block.

Also, the handleAddressChange does not returns AxiosPromise, instead it returns implicit promise, as it defined with async

So, something like this:

async handleAddressChange(): Promise<void> {
const url = `https://maps.googleapis.com/maps/api/place/autocomplete/json?key=${GoogleMapsApiKey}&input=${this.state.address}`;
    try {
      const { data } = await axios.get(url);
      this.setState({
        addressPredictions: data.predictions,
        showPredictions: true
      });
    } catch (err: AxiosError) {
      new Error(err);
    }
  }

Might work for you. Note the AxiosError definition.

One extra note is that you can add returned payload into the AxiosPromise generic, i.e.:

type TExpectedLoginResponse = {
    ok: boolean,
    token: string
}

export async function loginWithApi(creds: AuthParams): AxiosPromise<TExpectedLoginResponse> {
  const res = await axios.get(ApiUrls.login, { params: creds });
  return res.data; // so now flow knows that res.data is type of TExpectedLoginResponse
}

Hope it helps.

Related