You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在useFetch自定义Hook中指定响应类型并解决TS类型错误

解决useFetch自定义Hook的TypeScript类型错误

你遇到的错误核心是返回类型与state实际类型不匹配:你定义返回的data类型是ResponseType,但useState初始值为null,导致data的实际类型是ResponseType | null。当ResponseType是不允许为null的类型(比如string、非空接口)时,TypeScript会抛出类型不兼容的错误。

以下是几种可行的解决方案:

方案1:调整返回类型,补充异步状态(推荐)

实际场景中,异步请求存在加载中、请求失败的状态,同时请求完成前data确实是null,直接修改返回类型并补充加载和错误状态,既解决类型问题,也让Hook更实用:

import { useState, useEffect } from 'react';
import axios from 'axios';

function useFetchDemo<ResponseType>(url: string): {
  data: ResponseType | null;
  loading: boolean;
  error: Error | null;
} {
  const [data, setData] = useState<ResponseType | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<Error | null>(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const res = await axios.get(url);
        setData(res.data);
      } catch (err) {
        setError(err instanceof Error ? err : new Error('请求失败'));
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [url]);

  return { data, loading, error };
}

使用示例:

interface UserInterface {
  id: number;
  name: string;
}

const { data: user, loading, error } = useFetchDemo<UserInterface>("/users/123");

if (loading) return <div>加载中...</div>;
if (error) return <div>请求失败:{error.message}</div>;
return <div>用户名:{user?.name}</div>;

方案2:传入初始值,保证data始终为ResponseType类型

如果业务上需要data始终是非空的ResponseType,可以让调用者传入符合类型的初始值:

import { useState, useEffect } from 'react';
import axios from 'axios';

function useFetchDemo<ResponseType>(url: string, initialData: ResponseType): {
  data: ResponseType;
} {
  const [data, setData] = useState<ResponseType>(initialData);

  useEffect(() => {
    axios.get(url).then((res) => setData(res.data));
  }, [url]);

  return { data };
}

使用示例:

interface PostInterface {
  id: number;
  title: string;
}

// 传入符合PostInterface的初始值
const { data: post } = useFetchDemo<PostInterface>("/posts/123", { id: 0, title: "" });

方案3:类型断言(不推荐)

如果能保证请求一定会成功且返回数据符合ResponseType,可以用类型断言绕过检查,但这种方法会失去TypeScript的类型安全保障,不建议在生产环境使用:

function useFetchDemo<ResponseType>(url: string): {
  data: ResponseType;
} {
  const [data, setData] = useState<ResponseType | null>(null);

  useEffect(() => {
    axios.get(url).then((res) => setData(res.data));
  }, []);

  // 用类型断言强制转换
  return { data: data as ResponseType };
}

内容的提问来源于stack exchange,提问作者user18719885

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 16:24:32