TypeScript自定义API错误处理Hook报错:'doRequest'不存在于'any[]'类型
问题分析与解决方案
核心错误原因
你的useRequest Hook返回的是数组[doRequest, errors],但在SignUp组件中错误地使用了对象解构语法{doRequest, errors},TypeScript识别到返回值是数组类型,自然找不到对象属性doRequest,因此抛出该错误。
完整修正方案
1. 修正组件的解构方式
将SignUp组件中的对象解构改为数组解构:
// 原错误代码 const {doRequest, errors} = useRequest(...); // 修正后 const [doRequest, errors] = useRequest({ url: '/api/users/signup', method: 'post', body: { email, password } });
2. 完善Hook的类型定义(解决潜在类型问题)
除了核心错误,你的Hook还存在一些类型不严谨的地方,以下是优化后的完整Hook代码:
import axios, { AxiosError } from 'axios'; import { useState } from 'react'; // 限制请求方法为axios支持的类型,避免任意字符串 type HttpMethod = 'get' | 'post' | 'put' | 'delete' | 'patch'; interface UseRequestParams { method: HttpMethod; body: Record<string, unknown>; // 用更通用的对象类型替代object url: string; } // 后端返回的错误项类型(根据实际响应调整) interface ApiErrorItem { message: string; } // 后端错误响应结构 interface ApiErrorResponse { errors: ApiErrorItem[]; } const useRequest = ({ url, method, body }: UseRequestParams) => { // 明确errors的类型:React元素或null const [errors, setErrors] = useState<JSX.Element | null>(null); const doRequest = async () => { try { setErrors(null); // 请求前清空错误 const response = await axios[method](url, body); return response.data; } catch (err) { // 断言错误为AxiosError,获取正确的响应结构 const axiosErr = err as AxiosError<ApiErrorResponse>; setErrors( <div className="alert alert-danger"> <h4>Oooops.....</h4> <ul className="m-0"> {axiosErr.response?.data.errors.map((e) => ( <li key={e.message}>{e.message}</li> ))} </ul> </div> ); return null; } }; return [doRequest, errors] as const; // 使用as const让TypeScript推断精确的数组类型 }; export default useRequest;
3. 组件的其他小优化
可以给表单事件参数加上正确的类型,避免{ preventDefault: () => void }的模糊定义:
const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => { e.preventDefault(); await doRequest(); };
关键优化点说明
- 使用
as const断言Hook的返回数组,让TypeScript能准确推断数组元素的类型,避免被视为any[] - 限制HTTP方法为固定枚举类型,防止传入axios不支持的方法
- 明确错误状态的类型为React元素或null,避免类型模糊
- 对axios错误进行类型断言,安全访问响应数据中的错误信息
内容的提问来源于stack exchange,提问作者DirWolf
相关产品推荐
相关产品推荐

