Axios med TypeScript: Hur man berättar för Axios hur felresponser ser ut


Jag har en API-rutt (som använder Next.js API-rutter) som har en viss svarstruktur när den lyckas och en annan när ett fel uppstår.

export type ApiErrorResponse = { message: string };

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

export type GetCurrentUserHandlerResponse = ApiErrorResponse | SuccessResponse;

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

Hur kan jag tala om för Axios vilken form svaret har beroende på felet?

När jag abstraherar bort förfrågan på det här sättet:

const getCurrentUserRoute = '/api/user';

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

och använda getCurrentUserRequest måste jag alltid skilja på i både .then och i .catch om svaret har framgångsformen eller felformen.

I idealfallet letar jag efter något som detta:

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

I slutändan vill jag att TypeScript ska kunna göra detta:

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; }
  });

Finns det ett sätt att göra det med TypeScript?

Svar #1

Jag tror att du kanske antar en annan kodväg för fel än den du får med axios. Mer konventionellt skulle du implementera detta på ett async/await-sätt och i 'happy path' antar du bara alltid att datan har rätt form.

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

Det är bara i catch-satsen som du måste hantera felet, och i det fallet skulle du ÄNDÅ alltid behöva införa någon form av typvakt för att bekräfta den bevisade typen av begärans kropp eftersom det finns flera fel som kan uppstå när man gör en webbförfrågan.

...eller är ditt fall ett Fel som inte visar sig som ett fel på HTTP-lagret?