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

React D3设置数据时出现Object is of type 'unknown' TS报错

React D3自定义Hook TypeScript类型报错解决方案

问题背景

在React+D3项目中开发负责数据拉取、加工的自定义Hook时,先后遇到两类TypeScript报错:

  1. 初始实现时useEffect回调内抛出Object is of type 'unknown'错误
  2. 调整接口类型定义后,仍存在两处参数类型不匹配错误

错误根因分析

  • 初始unknown报错:D3内置的json()方法默认返回类型为Promise<unknown>,TypeScript无法自动推断拉取到的JSON数据结构,直接对返回值调用数组方法会触发类型校验错误。
  • 调整类型后的第一处报错:timeParse方法的入参要求为string类型,但调整后的联合类型string | Date | null无法保证传入值一定是合法字符串;同时错误地给json()传入了嵌套数组的泛型EventViewerDataTypes[],和本身定义为数组类型的EventViewerDataTypes结构冲突。
  • 调整类型后的第二处报错:D3的json()方法在请求异常、无返回内容时会返回undefined,该类型和useState定义的EventViewerDataTypes | null类型不匹配,无法直接传入setData。
  • 额外逻辑问题:原代码直接在forEach中修改接口返回的原始响应对象,违反React不可变数据原则,容易引发不可预期的渲染问题。

修复步骤

  • 拆分类型定义:分别定义接口返回的原始数据类型和加工完成后输出的数据类型,不要用联合类型混同两个阶段的数据结构
  • 给json()传入正确的泛型参数,明确拉取到的原始数据结构,避免数组嵌套
  • 增加空值收窄逻辑,处理json()返回undefined的边界场景,匹配state的类型要求
  • 用map替代forEach生成全新的加工后数据对象,不要直接修改原始响应
  • 将jsonUrl加入useEffect依赖数组,避免url变化时不重新拉取数据的闭包问题

正确实现代码

import { useState, useEffect } from "react"
import { json, timeParse } from "d3"

const parseTime = timeParse("%d-%m-%Y")

// 接口返回的原始数据结构
interface RawEventData {
  date: string
  site: string
  type: string
  value: string
}

// 加工完成后最终返回的数据结构
interface ProcessedEventData {
  date: Date | null
  site: string
  type: string
  value: number
}

export const useData = (jsonUrl: string) => {
  const [data, setData] = useState<ProcessedEventData[] | null>(null)
  
  useEffect(() => {
    // 传入原始数据类型泛型,此时json返回类型为Promise<RawEventData[] | undefined>
    json<RawEventData[]>(jsonUrl).then((rawData) => {
      // 空值收窄,处理无返回的场景
      if (!rawData) {
        setData(null)
        return
      }
      // 遍历加工生成新的数据对象,不修改原始响应
      const processedData = rawData.map((item) => ({
        date: parseTime(item.date), // 原始date为string类型,完全符合parseTime入参要求
        site: item.site,
        type: item.type,
        value: +item.value // 字符串转数字
      }))
      setData(processedData)
    })
  }, [jsonUrl])

  return data
}

提示:timeParse方法在日期格式不匹配时会返回null,如果业务场景不允许日期为空,可以在加工逻辑中增加空值校验,过滤无效数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 09:54:24