TypeGraphQL结合Prisma构建ObjectType关联时字段解析报错
问题描述
在搭配Apollo的TypeGraphQL项目中为两个ObjectType创建关联关系时,运行出现异常:
查询返回的category字段值为null,但关联数据实际已存在于Prisma ORM管理的数据源中。
原有FieldResolver实现代码如下:
@FieldResolver(() => Category) async categories(@Root() parent: Product, @Ctx() ctx:Context): Promise<Category[]> { return await ctx.prisma.category.findUnique({ where: {id: parent.id} }).categories()! }
触发的类型错误为:
Property 'categories' does not exist on type 'Prisma__CategoryClient<Category | null>'
问题原因排查
- 关联查询逻辑写反:当前代码是先查
category表再取关联的categories,但需求是根据根对象Product的ID查它关联的分类,外键关系方向搞反了。 - Prisma fluent API调用前提不满足:
findUnique如果查询结果可能为null,TypeScript会判定返回的客户端实例不存在后续关联查询方法,必须先保证查询条件命中唯一记录、或者做非空判断才能链式调用关联关系方法。 - 装饰器返回类型不匹配:
@FieldResolver装饰器声明的返回类型是单个Category,但方法实际声明返回Category[]数组,类型不一致会导致GraphQL序列化时返回null。 - 关联字段外键匹配错误:代码里用
parent.id(Product的主键)作为category表的查询条件,正常多对多/一对多关系下,应该通过Product本身的关联关系取分类,而不是直接用Product ID匹配分类主键。
修复方案
根据Product和Category的常规关联逻辑(通常为多对多:一个商品对应多个分类,一个分类对应多个商品),直接修改解析器即可:
// 修正装饰器返回类型为Category数组 @FieldResolver(() => [Category]) async categories(@Root() parent: Product, @Ctx() ctx: Context): Promise<Category[]> { // 从product表入口查询关联分类,避免关联方向写反,用findUniqueOrThrow保证结果非空 return ctx.prisma.product.findUniqueOrThrow({ where: { id: parent.id } }).categories() }
如果需要用条件查询的方式实现,也可以用以下写法,不需要依赖fluent API:
@FieldResolver(() => [Category]) async categories(@Root() parent: Product, @Ctx() ctx: Context): Promise<Category[]> { return ctx.prisma.category.findMany({ where: { // 替换为自身Prisma Schema中实际配置的关联字段 products: { some: { id: parent.id } } } }) }
额外校验项:
- 如果坚持使用
findUnique而非findUniqueOrThrow,需要先判断查询结果非空再调用关联方法,否则TypeScript仍会报类型错误 - 检查Prisma Schema中Product和Category的关联关系是否正确配置,执行
npx prisma generate重新生成客户端类型,清除类型缓存导致的方法不存在报错 - 确认查询Product主数据的解析器中,没有主动过滤关联分类字段,也没有权限中间件拦截导致分类字段返回null
内容的提问来源于stack exchange,提问作者Esore
相关产品推荐
相关产品推荐

