Jest测试中tRPC useQuery参数类型不匹配问题求助
问题原因及解决方案
核心原因
- Mock数据类型不匹配:测试中返回的mock数据没有严格遵循tRPC路由定义的返回类型,比如仅返回
{ id: string }缺少路由中定义的devices等其他字段,导致TypeScript类型校验失败。 - Mock的tRPC客户端丢失类型:手动mock
trpc.useQuery时,没有继承原tRPC路由的类型定义,导致TypeScript无法识别返回数据的结构(如user.devices)。 - Monorepo类型解析问题:monorepo中tRPC的类型文件路径未被正确配置,测试环境无法读取到路由定义的类型信息。
解决方案
1. 用tRPC生成的类型约束Mock数据
从tRPC路由定义中导出自动生成的返回类型,用它来约束mock数据,确保结构完全匹配:
// 导入tRPC路由生成的输出类型 import type { RouterOutputs } from '@/server/trpc/router'; // 定义完全符合类型的mock用户数据 const mockUser: RouterOutputs['user']['get'] = { id: 'user-123', devices: [{ id: 'device-001', model: 'iPhone 15' }], // 补充路由定义中所有必填字段 };
2. 正确Mock tRPC客户端并保留类型
方式一:使用tRPC官方测试工具
利用@trpc/react-query提供的测试能力,创建带类型的mock客户端:
import { createTRPCReact } from '@trpc/react-query'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { render } from '@testing-library/react-native'; import type { Router } from '@/server/trpc/router'; // 创建带路由类型的tRPC实例 const trpc = createTRPCReact<Router>(); // 构造mock客户端 const mockTRPCClient = trpc.createClient({ links: [ () => ({ async op() { return { data: mockUser }; // 使用符合类型的mock数据 }, }), ], }); // 在测试中用mock客户端包裹组件 test('显示用户设备列表', async () => { const queryClient = new QueryClient(); render( <trpc.Provider client={mockTRPCClient} queryClient={queryClient}> <UserDeviceComponent /> </trpc.Provider> ); // 执行测试断言逻辑 });
方式二:手动Mock时保留类型
如果手动mock useQuery,确保返回的数据类型与路由输出一致:
// 假设你的tRPC实例导出在@/utils/trpc jest.mock('@/utils/trpc', () => ({ useQuery: jest.fn(() => ({ data: mockUser, // 用符合RouterOutputs类型的mock数据 isLoading: false, error: null, })), }));
3. 修复Monorepo类型配置
检查React Native包的tsconfig.json,确保tRPC路由所在的目录被包含在类型解析范围内:
{ "include": [ "src/**/*", "../server/trpc/**/*" // 假设server包在monorepo的同级目录 ], "compilerOptions": { "baseUrl": ".", "paths": { "@/server/*": ["../server/*"] // 配置路径别名,确保类型能被正确解析 } } }
4. 安全替代ts-ignore的方式
如果需要临时调整类型,使用类型断言而非// @ts-ignore,明确告知TypeScript数据的真实类型:
const { data: user } = trpc.useQuery(['user.get']); // 用路由输出类型断言,替代ts-ignore const devices = (user as RouterOutputs['user']['get']).devices;
内容的提问来源于stack exchange,提问作者TempestWindblown
相关产品推荐
相关产品推荐

