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

如何为fetch()返回值指定类型?解决TypeScript类型不安全问题

修复TypeScript中fetch请求的ESLint不安全赋值错误

你遇到的问题核心是res.json()默认返回any类型,直接赋值给Activity类型变量时,TypeScript和ESLint无法确认返回数据的结构是否完全匹配,因此触发不安全赋值警告。下面提供几种不同场景下的修复方案:


方案1:使用类型断言(快速解决,无运行时校验)

直接通过类型断言告诉TypeScript,API返回的JSON结构符合Activity类型,快速消除ESLint警告:

type Activity = {
  activity: string
  type: string
  participants: number
  price: number
  link: string
  key: string
  accessibility: number
}

async function fetchOne(): Promise<Activity> {
  const url = "https://www.boredapi.com/api/activity"
  // 给res.json()添加类型断言
  const res = await fetch(url).then(res => res.json() as Activity)
  return res
}

注意:这种方式仅在编译阶段做类型提示,没有运行时校验,如果API返回的结构和Activity不匹配,运行时仍可能出现异常。


方案2:添加运行时类型守卫(最安全)

编写一个类型守卫函数,在运行时校验返回数据的结构,既满足TypeScript类型检查,又能避免异常数据导致的问题:

type Activity = {
  activity: string
  type: string
  participants: number
  price: number
  link: string
  key: string
  accessibility: number
}

// 类型守卫函数:校验数据是否符合Activity结构
function isActivity(data: unknown): data is Activity {
  return (
    typeof data === 'object' &&
    data !== null &&
    'activity' in data && typeof (data as Activity).activity === 'string' &&
    'type' in data && typeof (data as Activity).type === 'string' &&
    'participants' in data && typeof (data as Activity).participants === 'number' &&
    'price' in data && typeof (data as Activity).price === 'number' &&
    'link' in data && typeof (data as Activity).link === 'string' &&
    'key' in data && typeof (data as Activity).key === 'string' &&
    'accessibility' in data && typeof (data as Activity).accessibility === 'number'
  )
}

async function fetchOne(): Promise<Activity> {
  const url = "https://www.boredapi.com/api/activity"
  const rawData = await fetch(url).then(res => res.json())
  
  // 校验不通过则抛出错误
  if (!isActivity(rawData)) {
    throw new Error('API返回数据结构不符合预期')
  }
  
  return rawData
}

方案3:封装泛型fetch工具函数(复用性高)

如果有多个API请求需要做类型校验,可以封装一个通用的泛型工具函数,减少重复代码:

type Activity = {
  activity: string
  type: string
  participants: number
  price: number
  link: string
  key: string
  accessibility: number
}

// 泛型工具函数:接收URL和类型守卫,返回符合类型的结果
async function fetchAndValidate<T>(url: string, validator: (data: unknown) => data is T): Promise<T> {
  const response = await fetch(url)
  const rawData = await response.json()
  
  if (!validator(rawData)) {
    throw new Error('数据结构校验失败')
  }
  
  return rawData
}

// 复用工具函数请求Activity数据
async function fetchOne(): Promise<Activity> {
  const url = "https://www.boredapi.com/api/activity"
  return fetchAndValidate(url, (data): data is Activity => {
    return (
      typeof data === 'object' &&
      data !== null &&
      'activity' in data && typeof (data as Activity).activity === 'string' &&
      'type' in data && typeof (data as Activity).type === 'string' &&
      'participants' in data && typeof (data as Activity).participants === 'number' &&
      'price' in data && typeof (data as Activity).price === 'number' &&
      'link' in data && typeof (data as Activity).link === 'string' &&
      'key' in data && typeof (data as Activity).key === 'string' &&
      'accessibility' in data && typeof (data as Activity).accessibility === 'number'
    )
  })
}

内容的提问来源于stack exchange,提问作者Nicolas S.Xu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 10:42:33