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

Nuxt3中useFetch数据类型标注报错及JSON转对象方案咨询

解决方案

问题根源

你给useFetch指定的泛型是Tenant[],但实际API返回的JSON结构是包含tenants字段的对象,而非直接的租户数组。TypeScript因此将transform函数的参数_tenants推断为Tenant[]类型,自然找不到tenants属性,导致报错。

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

先明确API返回数据的结构,创建对应的TypeScript类型:

// ~/types/models.ts
export type Tenant = {
  id: number;
  name: string;
};

// 新增API响应类型,匹配实际返回的JSON结构
export type TenantsApiResponse = {
  tenants: Tenant[];
};

步骤2:修正useFetch的泛型与transform逻辑

将useFetch的泛型改为TenantsApiResponse,这样transform函数的参数类型就会正确匹配API返回的结构:

<script setup lang="ts">
import { Tenant, TenantsApiResponse } from '~/types/models'

const { data: tenants, pending, error, refresh } = await useFetch<TenantsApiResponse>(
  'http://localhost:3000/tenants',
  {
    headers: {
      'Authorization': auth.headers.Authorization
    },
    // 此时_tenants类型为TenantsApiResponse,可安全访问tenants字段
    transform: (_tenants) => _tenants.tenants,
  }
)
// 此时tenants的类型自动推断为Tenant[],符合需求
</script>

步骤3:抽离到Composable提升可维护性

按照你提到的最佳实践,将数据请求逻辑封装到composable中,方便复用和统一维护:

// ~/composables/useTenants.ts
import type { Tenant, TenantsApiResponse } from '~/types/models'

export const useTenants = async () => {
  const auth = useAuth() // 假设你有useAuth composable获取授权信息

  const { data: tenants, pending, error, refresh } = await useFetch<TenantsApiResponse>(
    'http://localhost:3000/tenants',
    {
      headers: {
        'Authorization': auth.headers.Authorization
      },
      transform: (res) => res.tenants,
    }
  )

  return { tenants, pending, error, refresh }
}

在组件中使用:

<script setup lang="ts">
const { tenants, pending, error, refresh } = await useTenants()
</script>

额外的类型安全建议

如果需要更强的运行时校验(比如API返回结构可能不符合预期),可以结合zod库定义schema,同时生成TypeScript类型:

// ~/schemas/tenant.ts
import { z } from 'zod'

const TenantSchema = z.object({
  id: z.number(),
  name: z.string(),
})

const TenantsApiResponseSchema = z.object({
  tenants: z.array(TenantSchema),
})

// 从zod schema生成TypeScript类型
export type Tenant = z.infer<typeof TenantSchema>
export type TenantsApiResponse = z.infer<typeof TenantsApiResponseSchema>

// 在composable中使用校验
export const useTenants = async () => {
  const auth = useAuth()

  const { data: tenants, pending, error, refresh } = await useFetch<TenantsApiResponse>(
    'http://localhost:3000/tenants',
    {
      headers: {
        'Authorization': auth.headers.Authorization
      },
      transform: (res) => {
        // 运行时校验API返回数据
        const validated = TenantsApiResponseSchema.parse(res)
        return validated.tenants
      },
    }
  )

  return { tenants, pending, error, refresh }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 06:35:22