我目前面临的问题是,我不能使用从承诺拒绝返回的错误,因为它不能与Typescript类型。例如,当注册请求失败时,因为用户名已经被占用,我返回message
username already taken
的400
。但是我无法从错误中访问消息,因为无法键入try catch
中的error
对象。
axios是否可以处理这种情况,并且可以使用自定义类型访问错误对象?
或者我应该在数据下创建一个错误对象,当服务器有一个200
或返回一个错误对象时,将其返回为null
?
的例子:
export interface ErrorRes {
statusCode: number;
error: string;
message: string;
}
export interface ISignupRes {
token: string;
user: IUser;
message: string;
}
const handleSignUp = async () => {
setLoading(true)
try {
const { data, status }: { data: ISignupRes; status: number } =
await coreApi.post('/auth/signup', {
email,
username,
firstname,
lastname,
password,
})
if (status === 200) {
Storage.save(true, 'token', data.token)
addNotification({
type: 'success',
message: data.message,
})
} else {
// this never get's called because if the response returns an error it get's catched
addNotification({
type: 'error',
message: data.message,
})
}
setLoading(false)
} catch (error) {
// the error is of type `unkown` to I can't access `error.message`
setLoading(false)
addNotification({
type: 'error',
message: error.message,
})
}
}
Typescript没有办法验证axios错误是代码可能抛出的唯一错误,因此Typescript catch块中的错误总是unknown
或any
。你的编译器设置显然更喜欢unknown
。
若要将错误视为其他错误,您要么需要放入一些代码来检查抛出的是什么类型,要么需要使用类型断言来坚持typescript知道该类型是什么。幸运的是,axios库包含一个帮助函数,它可以为您执行检查,并且它具有适当的类型来缩小错误对象的范围:
} catch (error) {
if (axios.isAxiosError(error) {
// inside this block, typescript knows that error's type is AxiosError<any>
setLoading(false)
addNotification({
type: 'error',
message: error.message,
})
} else {
// In this block, error is still of type `unknown`
}
}
我发现有一个方法对输入Axios错误很有帮助,我在这里发现了用户btraut:
添加:
export function isAxiosError<ResponseType>(error: unknown): error is AxiosError<ResponseType> {
return axios.isAxiosError(error);
}
,然后使用下面的MyExpectedResponseType替换为您希望错误对象的类型。
type MyExpectedResponseType = {
thisIsANumber: number;
};
try {
// Make the axios fetch.
} catch (error: unknown) {
if (isAxiosError<MyExpectedResponseType>(error)) {
// "thisIsANumber" is properly typed here:
console.log(error.response?.data.thisIsANumber);
}
}
您还可以使用响应拦截器为每个请求包装一个try-catch块。
axios.interceptors.response.use(undefined, (error) => {
if (axios.isAxiosError(error)) {
throw new HttpRequestError("Request Failed: " + error.response?.data);
} else {
return Promise.reject(error);
}
});