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
相关产品推荐
相关产品推荐

