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

TypeScript中API返回unknown类型对象的类型定义与遍历报错问题

问题解决与写法合规性说明

报错原因

TypeScript报错的核心是**fetch返回的JSON数据默认是unknown类型**,你直接把Object.values(data.races)的遍历值指定为RaceInfo,但TypeScript无法确认data.races的结构确实符合预期的键值对格式,因此判定类型不兼容。

解决forEach报错的方案

步骤1:定义完整的API响应类型

先给接口返回的整个数据结构声明类型,明确races是“字符串键 + RaceInfo值”的对象:

interface ApiResponse {
  success: boolean;
  races: Record<string, RaceInfo>;
}

步骤2:给JSON数据指定类型

通过类型断言或类型守卫,让TypeScript识别API返回数据的结构:

方式一:类型断言(简单直接)

export default async function getSC(selection: Selection) {
  let sc: string | undefined; // 给sc声明明确类型,避免隐式any

  await fetch(`URL`, { method: "GET" })
    .then((response) => response.json() as ApiResponse) // 断言为ApiResponse类型
    .then((data) => {
      if (data.success) {
        // 此时Object.values(data.races)自动推导为RaceInfo[]
        Object.values(data.races).forEach((value) => {
          if (
            value.codes.race_sc.slice(-4) === selection.time &&
            value.details.venue === selection.venue
          ) {
            sc = value.codes.race_sc;
          }
        });
      } else {
        console.log("Could not fetch the races");
      }
    })
    .catch((error) => {
      console.log("Error:", error);
    });

  return sc;
}

方式二:类型守卫(更严谨,适合不确定API返回结构的场景)

// 定义类型守卫函数,验证数据是否符合ApiResponse结构
function isApiResponse(data: unknown): data is ApiResponse {
  return (
    typeof data === 'object' &&
    data !== null &&
    'success' in data &&
    typeof (data as ApiResponse).success === 'boolean' &&
    'races' in data &&
    typeof (data as ApiResponse).races === 'object' &&
    (data as ApiResponse).races !== null
  );
}

export default async function getSC(selection: Selection) {
  let sc: string | undefined;

  await fetch(`URL`, { method: "GET" })
    .then((response) => response.json())
    .then((data) => {
      if (isApiResponse(data) && data.success) {
        // 这里data.races会被正确推导为Record<string, RaceInfo>
        Object.values(data.races).forEach((value) => {
          if (
            value.codes.race_sc.slice(-4) === selection.time &&
            value.details.venue === selection.venue
          ) {
            sc = value.codes.race_sc;
          }
        });
      } else {
        console.log("Could not fetch the races");
      }
    })
    .catch((error) => {
      console.log("Error:", error);
    });

  return sc;
}

for...of写法的合规性说明

你当前的for...of写法不符合严格TypeScript规范,原因如下:

  1. data.races是unknown类型,Object.keys(data.races)返回的string[]无法直接关联到data.races的键类型,直接访问value.codes会在严格模式下触发类型报错(你当前可能关闭了严格检查所以未报错)。
  2. 变量sc未声明类型,会被隐式推导为any,违背TypeScript的类型安全原则。

修正后的合规for...of写法

结合前面定义的ApiResponse类型,修正后写法如下:

export default async function getSC(selection: Selection) {
  let sc: string | undefined;

  await fetch(`URL`, { method: "GET" })
    .then((response) => response.json() as ApiResponse)
    .then((data) => {
      if (data.success) {
        for (const key of Object.keys(data.races)) {
          const value = data.races[key]; // 自动推导为RaceInfo类型
          if (
            value.codes.race_sc.slice(-4) === selection.time &&
            value.details.venue === selection.venue
          ) {
            sc = value.codes.race_sc;
          }
        }
      } else {
        console.log("Could not fetch the races");
      }
    })
    .catch((error) => {
      console.log("Error:", error);
    });

  return sc;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 22:11:04