I have an Ionic React app written in TypeScript. Upon attempting to upgrade to 4.8 this morning, I am getting Object is of type 'unknown'.
for Axios responses.
This code worked fine in 4.7 but TypeScript 4.8 refuses to build my app.
Here's the code at issue:
const handleErrorsPostAuth = (error: AxiosError) => {
if (error?.response) {
// Object is of type 'unknown' for the line below.
if (error.response.data.errors[0]) {
// Object is of type 'unknown' for the line below.
throw new Error(error.response.data.errors[0].detail);
}
throw new Error(error.response.toString());
}
throw new Error(error.message);
};
I read the TypeScript 4.8 release notes and found under breaking changes that lib.d.ts updates included:
While TypeScript strives to avoid major breaks, even small changes in the built-in libraries can cause issues. We don’t expect major breaks as a result of DOM and lib.d.ts updates, but one notable change is that the cause property on Errors now has the type unknown instead of Error.
My issue is with response
, not cause
, so I'm not sure if this is the issue I'm experiencing.
Here's the AxiosResponse
interface from axios index.d.ts:
export interface AxiosResponse<T = any, D = any> {
data: T;
status: number;
statusText: string;
headers: AxiosResponseHeaders;
config: AxiosRequestConfig<D>;
request?: any;
}
I tried to add a check with instanceof
like this:
if (error?.response && error.response instanceof AxiosResponse) {
But this doesn't work because AxiosResponse
is an interface and it seems there is no way to check whether an object implements an interface in TypeScript, only whether an object is of a given type.
So, how do I correctly check for an axios response now? This may be obvious but I don't really understand how the axios types work-- I think I need to narrow the type to ensure I have an AxiosResponse and not unknown, but I don't know how to do that.
As we can see here AxiosError is a Generic https://github.com/axios/axios/blob/bdf493cf8b84eb3e3440e72d5725ba0f138e0451/index.d.ts#L276
Where T is unknown by default. T is used to create the type of the Response https://github.com/axios/axios/blob/bdf493cf8b84eb3e3440e72d5725ba0f138e0451/index.d.ts#L288
So you should be able to do something like this:
type MyErrorResponse = {
errors: {detail: string}[]
}
const handleErrorsPostAuth = (error: AxiosError<MyErrorResponse>) => {
if (error?.response) {
// Object is of type 'unknown' for the line below.
if (error.response.data.errors[0]) {
// Object is of type 'unknown' for the line below.
throw new Error(error.response.data.errors[0].detail);
}
throw new Error(error.response.toString());
}
throw new Error(error.message);
};