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

如何解决useFetch Hook中never[]无法赋值给T的TypeScript错误?

如何解决useFetch Hook中useState初始化的类型错误?

需求

希望useFetch自定义Hook能够接受任意类型的数组作为data的类型。

现有代码

hooks/useFetch.ts

const useFetch = <T extends any[]>(dataUrl: string) => {
  const [data, setData] = useState<T>([]);
  const [error, setError] = useState<string | null>(null);
  const result = await axios(dataUrl);
  
  setData(result.data);
}

说明:result类型为AxiosResponse<any, any>,成功返回的result.data应为对象数组。

App.tsx

interface City {
  rank: number;
  city: string;
  state: string;
  population: string;
}

const { data: cities, error } = useFetch<City[]>('/data.json');

错误信息

在代码行const [data, setData] = useState<T>([]);处出现如下错误:

Argument of type 'never[]' is not assignable to parameter of type 'T | (() => T)'.

解决方案

1. 直接给初始值添加类型断言

因为T被约束为任意数组类型,但空数组[]的默认类型是never[],无法直接匹配T。可以通过类型断言告诉TypeScript该空数组符合T的类型要求:

const [data, setData] = useState<T>([] as T);

2. 调整泛型设计(更严谨的方案)

把泛型定义为数组元素的类型,而非整个数组类型,这样初始值的类型逻辑会更清晰,同时修复原代码中await使用的错误:

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

const useFetch = <T>(dataUrl: string) => {
  const [data, setData] = useState<T[]>([]);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const result = await axios(dataUrl);
        setData(result.data as T[]);
      } catch (err) {
        setError(err instanceof Error ? err.message : '请求发生未知错误');
      }
    };

    fetchData();
  }, [dataUrl]);

  return { data, error };
};

此时使用Hook时只需传入数组元素的类型即可:

const { data: cities, error } = useFetch<City>('/data.json');

额外注意

原代码还有两处隐性问题需要修正:

  • await必须在async函数内使用,因此要把请求逻辑包裹在async函数中,并结合useEffect执行(自定义Hook顶层不能是async函数)
  • Hook需要返回data和error,否则组件无法通过解构获取这些值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 09:18:13