Typing Axios Error Responses in TypeScript
Handling and typing API error responses correctly in TypeScript with
Axios requires moving away from unsafe type assertions
(as AxiosError) and leveraging Axios's built-in type
guards. Since TypeScript sets errors in catch blocks to
unknown by default, the proper approach involves defining a
custom interface for your backend error payload and validating the error
using axios.isAxiosError<T>(). This guide explains
how to strongly type Axios error responses safely and efficiently.
1. Define the Expected Error Response Interface
Backends typically return a structured JSON response when a request fails (e.g., a 400 or 500 status code). Define a TypeScript interface that mirrors this schema:
interface ApiErrorResponse {
message: string;
statusCode: number;
errors?: Record<string, string[]>;
}2. Use
axios.isAxiosError as a Type Guard
Axios provides a built-in type guard called
axios.isAxiosError. This function checks if an unknown
error object is an AxiosError at runtime and narrows the
type in TypeScript.
You can pass your error response interface as a generic type argument
to axios.isAxiosError<T>:
import axios from 'axios';
async function fetchUserData(userId: string) {
try {
const response = await axios.get(`/api/users/${userId}`);
return response.data;
} catch (error: unknown) {
if (axios.isAxiosError<ApiErrorResponse>(error)) {
// error is now typed as AxiosError<ApiErrorResponse>
if (error.response) {
// The server responded with a status code outside the 2xx range
console.error('API Error Message:', error.response.data.message);
console.error('Status Code:', error.response.status);
} else if (error.request) {
// The request was made but no response was received (e.g., network error)
console.error('Network Error: No response received');
} else {
// Something went wrong setting up the request
console.error('Axios Setup Error:', error.message);
}
} else {
// Non-Axios error (e.g., native JavaScript runtime error)
console.error('Unexpected Error:', error);
}
}
}3. Handle Axios Response Typing in Custom Utilities
If you are writing a reusable wrapper or service layer, you can create a helper function to extract error messages safely:
import axios from 'axios';
export function getErrorMessage(error: unknown): string {
if (axios.isAxiosError<ApiErrorResponse>(error)) {
return error.response?.data?.message ?? error.message;
}
if (error instanceof Error) {
return error.message;
}
return 'An unknown error occurred';
}4. Why
Avoid Direct Type Casting (error as AxiosError)
Direct casting with
catch (error) { const err = error as AxiosError; } bypasses
TypeScript’s runtime safety. If an unhandled JavaScript exception occurs
inside your try block (such as a TypeError
from parsing JSON), treating it unconditionally as an
AxiosError can cause error.response lookups to
fail or produce runtime bugs. Using axios.isAxiosError()
ensures your code only accesses Axios-specific properties when the error
actually originates from an Axios request.