TypeScript中Axios后端数据类型、错误类型及代码优化问询
重置密码代码问题解答与优化
1. 表单提交函数的参数e类型声明是否正确?
正确。React.FormEvent<HTMLFormElement>准确描述了表单提交事件的类型,事件目标是HTMLFormElement,preventDefault()方法也属于该类型的标准方法,完全适配表单提交场景。
2. catch块错误的理想类型是什么?
不要用any,推荐用**AxiosError | Error**(需从axios导入AxiosError类型),或者更精确的AxiosError<{ message?: string }>来捕获Axios请求的错误细节。如果用unknown作为兜底类型,再通过类型守卫判断错误类型,能更安全地处理不同场景:
- Axios错误可获取响应体中的自定义错误信息(如
error.response?.data.message) - 原生Error可获取错误栈或基础描述信息
3. 后端返回JSON数据的类型声明
应在函数外部定义语义化的接口/类型,避免内部重复声明,示例如下:
interface ResetPasswordResponse { message: string; success: boolean; }
之后在Axios请求时通过泛型指定,让response.data自动推导为该类型,无需手动断言:
const response = await axios.post<ResetPasswordResponse>('/api/resetpassword', {...});
4. 代码优化方案
从结构扁平化、类型安全、错误精细化处理、可读性几个方向优化:
- 提前退出:密码不匹配时直接提示并return,去掉else嵌套,让代码更扁平
- 外部定义类型:把响应类型、表单信息类型移到函数外,提升复用性和可读性
- 利用Axios泛型:自动推导响应数据类型,减少类型断言
- 精细化错误处理:区分Axios错误和原生错误,展示更具体的错误信息
- 增加表单信息类型约束:避免
info对象属性类型混乱 - 可选:添加loading状态,防止用户重复提交
优化后的完整代码
import { AxiosError } from 'axios'; import { useState } from 'react'; import { toast } from 'react-toastify'; import { useRouter } from 'next/router'; // 定义后端响应类型 interface ResetPasswordResponse { message: string; success: boolean; } // 定义表单输入信息的类型 interface ResetPasswordFormInfo { token: string; password: string; confirm_password: string; } const ResetPasswordPage = () => { const [info, setInfo] = useState<ResetPasswordFormInfo>({ token: '', password: '', confirm_password: '' }); const [isLoading, setIsLoading] = useState(false); const router = useRouter(); const handleResetPassword = async (e: React.FormEvent<HTMLFormElement>) => { e.preventDefault(); if (isLoading) return; // 防止重复提交 // 密码校验不通过,直接退出 if (info.password !== info.confirm_password) { toast.error("密码不匹配"); return; } setIsLoading(true); try { const response = await axios.post<ResetPasswordResponse>('/api/resetpassword', { token: info.token, password: info.password }); const { success, message } = response.data; if (success) { toast.success(message); router.push('/login'); } else { toast.error(message); } } catch (error: unknown) { let errorMessage = "发生未知错误,请稍后重试"; if (error instanceof AxiosError) { // 优先取后端返回的错误信息 errorMessage = error.response?.data?.message || "重置密码失败,请检查链接或稍后重试"; } toast.error(errorMessage); } finally { setIsLoading(false); // 无论成功失败都重置loading状态 } }; return ( <form onSubmit={handleResetPassword}> {/* 省略表单输入元素 */} <button type="submit" disabled={isLoading}> {isLoading ? "重置中..." : "重置密码"} </button> </form> ); }; export default ResetPasswordPage;
内容的提问来源于stack exchange,提问作者LOKESH R
相关产品推荐
相关产品推荐

