使用Prisma与TRPC时TypeScript无法识别关联字段的问题
Prisma + TRPC + TypeScript 关联查询类型推断异常问题
问题现象
使用Prisma、TRPC和TypeScript开发时,查询包含关联模型的用户数据,接口能正常返回预期结果,但VSCode抛出TypeScript警告:
Property 'posts' does not exist on type '{ id: string; id: string; }'.
客户端代码
const includeFields = { posts: true, }; type UserWithPosts = Prisma.UserGetPayload<{ include: typeof includeFields }>; const { data, isLoading } = trpc.user.findMany.useQuery<UserWithPosts[]>( { include: includeFields }, {} ); if (!isLoading && data) { const firstUser = data[0]; if (firstUser) { console.log(firstUser.posts); // 此处出现警告 } }
Prisma Schema定义
model User { id String @id @default(cuid()) name String posts Post[] // 关联Post模型 } model Post { id String @id @default(cuid()) title String userId String user User @relation(fields: [userId], references: [id]) }
TRPC服务端路由定义
export const usersRouter = t.router({ findMany: t.procedure.input(UserFindManySchema).query(async ({ ctx, input }) => { return await ctx.prisma.user.findMany(input); }) });
预期结果
TypeScript能根据传入Prisma的include参数,自动推断返回的用户对象包含posts字段,消除类型警告。
已尝试方案
- 将
include对象直接内联到useQuery调用中 - 给
includeFields添加as const标记
关键发现
服务端直接调用prisma.user.findMany({ include: { posts: true } })时,TypeScript能正确推断返回类型;但通过TRPC路由调用时,类型信息丢失,导致客户端无法识别posts字段。
解决方案
问题核心是TRPC路由未正确传递Prisma的类型信息,需调整路由的输入Schema和类型推断逻辑:
1. 修正输入Schema定义
确保UserFindManySchema与Prisma的UserFindManyArgs类型对齐,让TRPC能识别include参数的结构:
import { z } from "zod"; import type { Prisma } from "@prisma/client"; // 定义与Prisma UserFindManyArgs对齐的Zod Schema const UserFindManySchema = z.object({ include: z.object({ posts: z.boolean().optional(), }).optional(), // 可按需添加其他findMany支持的参数(如where、select等) }) satisfies z.ZodType<Prisma.UserFindManyArgs>;
2. 让TRPC自动推断返回类型
无需手动指定路由的返回类型,TRPC会根据prisma.user.findMany(input)的返回值自动推断类型:
export const usersRouter = t.router({ findMany: t.procedure.input(UserFindManySchema).query(async ({ ctx, input }) => { return ctx.prisma.user.findMany(input); }), });
3. 客户端简化调用(可选)
客户端无需手动指定useQuery的泛型,TRPC会根据传入的include参数自动推断返回数据类型:
const includeFields = { posts: true } as const; const { data, isLoading } = trpc.user.findMany.useQuery({ include: includeFields }); if (!isLoading && data) { console.log(data[0]?.posts); // 类型推断正常,无警告 }
内容的提问来源于stack exchange,提问作者Svante Grundström
相关产品推荐
相关产品推荐

