DevOverflow
DevOverflow

Reputation: 1762

How do you type an error property in a catch block in TypeScript?

I have this code:

import axios, {AxiosError} from "axios";

try {
  some request
} catch(err:AxiosError) {
 console.log(error.response) // Doesn't work
 console.log(error.response?.data?.message) // Doesn't work
 if(error.response?.data?.statusCode === 401) {
   logout()
 }
}

I can't check the status code inside because of TypeScript. How do I describe the error type correctly without resorting to the any type? I couldn't find how people handle this error in TypeScript, maybe I'm missing something.

Upvotes: 29

Views: 39340

Answers (5)

darmis
darmis

Reputation: 3299

This also depends on the axios version, in my case (axios 0.24.0) I could not use e instanceof AxiosError. So I use AxiosStatic.isAxiosError.

  import AxiosStatic from 'axios';

  try {
    await onPostingSomething();
  } catch (e: unknown) {
    if (!AxiosStatic.isAxiosError(e)) {
      throw e;
    }

    if (e.response?.status === 401) {
      console.log('errors.unauthorized');
    } else {
      console.log('errors.otherErrors');
    }
  }

Upvotes: 2

Bart Dorsey
Bart Dorsey

Reputation: 321

The best way to do this, is to explicitly check for the Error you expect to get. In this case, if you want to check if it's an AxiosError do the following:

import axios, {AxiosError} from "axios";

try {
  some request
} catch(err) {
 if (err instanceof AxiosError) {
   console.log(error.response);
   if(error.response?.data?.statusCode === 401) {
     logout();
   } 
 } else {
   // it was some other kind of error, handle it appropriately
 } 

By checking if it's an instance of AxiosError, in the if block we narrow the type of the err variable to be AxiosError. In the examples where people are using as to cast the Error, that could be incorrect because the error might NOT be an AxiosError but some other kind of error, which would result in a runtime error.

Upvotes: 16

Ryan O'Neill
Ryan O'Neill

Reputation: 5707

I encountered this as well, you can do it and @David-Easley hints at but does not provide the syntax.

If you surround the error variable with brackets, you can then set the type.

Change it from;

  .catch(error => {

to;

  .catch((error:AxiosError) => {

That gives intellisense on the error object.

Just make be sure that you'll always get that error type passed.

Upvotes: 0

David Easley
David Easley

Reputation: 1383

Alternatively, rather than use a regular catch block, restructure the code to use the Promise.catch(error) method. You can then quote the type of the parameter as (error: AxiosError) or just leave TypeScript to infer the type.

e.g., assuming "some request" is a GET request, it might look like this:

import axios from 'axios';

await (async () => {
  axios
    .get('some-url')
    .then((response) => {
      // Some handler logic
    })
    .catch((error) => {
      console.log(error.response); // now works
      console.log(error.response?.data?.message); // now works
      if (error.response?.data?.statusCode === 401) {
        logout()
      }
    });
})();

Upvotes: 0

Nicholas Tower
Nicholas Tower

Reputation: 85201

Typescript has no way to verify which types of values might be thrown by arbitrary code. So up until recently, the error had to be of type any.

} catch (err: any) {

From version 4.0 onward, typescript also allows unknown.

} catch (err: unknown) {

Anything else is not supported. If you want something more specific, you will either need to write code to narrow down what type of thing was thrown, or you will need to use a type assertion. Keep in mind that a type assertion is a way to tell typescript "i know more than you do, so don't check my work". If you assert that it's an AxiosError, but it could actually be something else, typescript cannot point out that mistake to you.

catch (err: unknown) {
   const error = err as AxiosError;
   //...
}

Upvotes: 33

Related Questions