TypeScript中useGet自定义Hook的IStatus接口定义问题
自定义useGet Hook的类型优化方案
1. 解决Error类型赋值报错问题
TypeScript中catch捕获的error默认类型是unknown,直接赋值给Error | AxiosError | null类型会触发类型不兼容报错。需要先对error进行类型校验再赋值:
- 导入AxiosError类型:
import axios, { AxiosError } from 'axios' - 在catch块中通过
instanceof判断error的具体类型,再完成赋值
2. 合理定义data的类型
不要固定设为空数组[],不同接口可能返回对象、数组等不同结构。推荐用泛型让调用者指定返回数据的类型,让Hook具备通用性。
优化后的useGet.ts代码
import { useEffect, useState } from 'react' import axios, { AxiosError } from 'axios' // 泛型状态接口,支持自定义data类型 interface IStatus<T> { loading: boolean; error: null | Error | AxiosError; data: null | T; } // 泛型Hook,调用时传入返回数据类型 export const useGet = <T>(url: string) => { const [status, setStatus] = useState<IStatus<T>>({ loading: true, error: null, data: null }); useEffect(() => { getData(); }, [url]); // 将url加入依赖,url变化时自动重新请求 const getData = async () => { try { const res = await axios(url); setStatus({ loading: false, error: null, data: res.data }); } catch (error) { let typedError: Error | AxiosError | null = null; // 精准判断error类型 if (error instanceof AxiosError) { typedError = error; } else if (error instanceof Error) { typedError = error; } else { // 兜底处理非Error类型异常 typedError = new Error(String(error)); } setStatus({ loading: false, error: typedError, data: null }); console.error(error); } } // 固定返回值类型,确保调用端类型推断准确 return [status.data, status.loading, status.error] as const; }
优化后的Component.tsx代码
import { useGet } from '../hooks/useGet'; const UseGetComponent = () => { interface IUser { id: number; name: string; email: string; } interface IPost { id: number; userId: number; title: string; } // 调用时指定泛型类型,自动获得类型推断 const [dataUsers, loadingUsers, errorUsers] = useGet<IUser[]>('https://jsonplaceholder.typicode.com/users') const [dataPosts, loadingPosts, errorPosts] = useGet<IPost[]>('https://jsonplaceholder.typicode.com/posts') return ( <> <h1>Custom hooks</h1> {loadingUsers && <div>Loading...</div>} {errorUsers && <div>Error: {errorUsers.message}</div>} {dataUsers && ( <div > <ul> // TypeScript已自动推断user为IUser类型,无需手动指定 {dataUsers.map((user) => ( <li key={user.id}> {user.name} - {user.email} {loadingPosts && <div>Loading...</div>} {errorPosts && <div>Error: {errorPosts.message}</div>} {dataPosts && ( <ul> {dataPosts .filter((post) => post.userId === user.id) .map((post) => ( <li key={post.id}>{post.title}</li> ))} </ul> )} </li> ))} </ul> </div> )} </> ) } export default UseGetComponent
关键优化点说明
- 泛型支持:适配不同类型的返回数据,调用端类型推断更准确,无需重复手动指定类型
- Error类型处理:通过
instanceof精准判断异常类型,解决类型不兼容问题,同时兜底处理非标准异常 - 依赖项修复:将url加入useEffect依赖数组,确保url变更时自动重新请求
- data类型灵活性:不再固定为数组,由调用者按需指定,适配不同接口的返回结构
内容的提问来源于stack exchange,提问作者sonEtLumiere
相关产品推荐
相关产品推荐

