Axios with TypeScript: How to tell Axios the error response shape

Viewed 663

I have an API route (using Next.js API routes) that has a certain response shape when successful and another when an error occurs.

export type ApiErrorResponse = { message: string };

export type SuccessResponse = {
  user: UserSession | null;
};

export type GetCurrentUserHandlerResponse = ApiErrorResponse | SuccessResponse;

const getCurrentUserHandler: NextApiHandler<GetCurrentUserHandlerResponse> = () => { /* ... */ };

How can I tell Axios what the shape of the response is depending on the error?

When I abstract away the request like this:

const getCurrentUserRoute = '/api/user';

const getCurrentUserRequest = () =>
  axios.get<GetCurrentUserHandlerResponse>(getCurrentUserRoute);

and use getCurrentUserRequest I always have to distinguish in both .then and in .catch whether the response is of the success shape, or of the error shape.

Ideally I'm looking for something like this:

const getCurrentUserRequest = () =>
  axios.get<SuccessResponse, ApiErrorResponse>(getCurrentUserRoute);

Ultimately I want TypeScript to be able to do this:

getCurrentUserRequest()
  .then((response) => {
    // now TS knows response.data is of the shape { user: UserSession | null; }
  })
  .catch((error) => {
    // now TS knows error.response.data is { message: string; }
  });

Is there a way to do that with TypeScript?

1 Answers

I think you might be assuming a different code path for errors than the one you get with axios. More conventionally you would be implementing this in an async/await fashion and in the 'happy path' you just always assume the data is of the right shape.

  try {
    const response = await apiClient.get<MyObj>('/endpoint');
    const myObj: MyObj = response.data;
    return myObj;
  } catch (err) {
    // use explicit separation of error cases here
  }

It's only in the catch clause that you have to handle the error, and in that case you would ALWAYS have to introduce some kind of typeguard anyway to assert the proven type of the request body since there are multiple errors which could arise when making a web request.

...or is your case an Error which doesn't present as an error at the HTTP layer?

Related