Typing Axios response based on status code

Viewed 39

I have a backend api that sends back responses in two different scenarios.

When successful, it sends

{
  lastConnectedAt: Date; 
}

if the request was bad, it sends below object with 404 status code.

{
  error: {
    message: string;
  };
}

In typescript, how should I type both scenarios?

export interface GenericErrorResponse {
  error: {
    message: string;
  };
}

export interface LoginSuccessResponse {
  lastConnectedAt: Date;
}

import { AxiosInstance } from "axios";
import { authApi } from "../apis/auth/authApi";
import { LoginSuccessResponse } from "../apis/auth/types";

class AuthService {
  constructor(private api: AxiosInstance) {}

  public requestLogin = async (email: string, password: string) => {
    const { data } = await this.api.post<LoginSuccessResponse>("/api/login", { email, password });
    return data;
  };
}

export default new AuthService(authApi);

As you see, I typed the successful response. But how on the other side?

1 Answers

data will always be of type LoginSuccessResponse. A 404 error will make axios throw an error. That can have many reasons, you can narrow it down like this:

function isAxiosError(error: unknown): error is AxiosError {
  return (error as AxiosError).isAxiosError !== undefined
}

...
try {
  const { data } = await this.api.post<LoginSuccessResponse>('/api/login', {
    email,
    password,
  })
  return data
} catch (err) {
  if (isAxiosError(err) && err.response?.status == 404) {
    // handle 404 error
  } else {
    // Handle all other errors
  }
}
...

If you want requestLogin to return either data or an error you can "handle" the error by returning it (return err as GenericErrorResponse). Return type of your function would then be Promise<LoginSuccessResponse | GenericErrorResponse>.

Related