GraphQL报错:Abstract type运行时需解析为Object类型,求排查
解决GraphQL Union类型
UserDetails解析失败的问题 核心问题分析
你遇到的报错根源主要有三个:
- Union解析器键名错误:你在
UserResolvers中用了字段名userDetails作为解析器键,但GraphQL要求Union类型的解析器必须使用Union类型本身的名称(即UserDetails)。 __resolveType依赖的字段不存在:你的解析器尝试从obj(也就是Customer/Admin/Gardener的文档对象)中读取userType,但这些子模型的文档里并没有存储该字段——userType只存在于主User模型中,导致解析器无法识别类型。- 查询函数与Schema定义不匹配:Schema中定义的Query字段是
login,但你的解析器函数命名是loginCustomer,会导致GraphQL无法映射到正确的 resolver。
具体修复方案
1. 修正Union解析器的键名与逻辑
利用父对象(上层的User对象)的userType来判断Union类型,无需修改子模型数据:
export const UserResolvers = { // 这里必须用Union类型名UserDetails,而非字段名userDetails UserDetails: { __resolveType: (obj, parent) => { switch(parent.userType) { case "customer": return "Customer"; case "admin": return "Admin"; case "gardener": return "Gardener"; default: throw new Error("User type not found"); } }, }, };
2. 修正查询函数的命名
确保resolver函数名与Schema中定义的Query字段一致:
export const UserQuery = { // 改为login,对应Schema中的extend type Query { login(...) } login: async (_, args) => { const { email, password, userType } = args.credentials; const user = await UserModel.findOne({ email, userType }); if (!user) { throw new Error("User not found"); } const isMatch = await user.comparePassword(password); if (!isMatch) { throw new Error("Incorrect password"); } if (user.bannedStatus) { throw new Error("User is banned"); } let userDetails; switch (userType) { case "customer": userDetails = await CustomerModel.findOne({ userID: user._id }); break; case "admin": userDetails = await AdminModel.findOne({ userID: user._id }); break; case "gardener": userDetails = await GardenerModel.findOne({ userID: user._id }); break; default: throw new Error("User type not found"); } return { email: user.email, userType: user.userType, userDetails: userDetails, }; }, };
备选方案:给子模型文档注入userType字段
如果不想依赖父对象,也可以在查询时给userDetails添加userType字段:
// 在login函数的return语句中修改 return { email: user.email, userType: user.userType, userDetails: { ...userDetails.toObject(), // 将Mongoose文档转为普通对象 userType: user.userType }, };
此时原有的__resolveType逻辑即可生效,但需要确保解析器键名改为UserDetails。
额外验证点
- 确认
Customer/Admin/Gardener类型在Schema中已正确定义,字段与模型匹配 - 检查Mongoose查询是否返回有效数据(可在login函数中打印
userDetails确认)
内容的提问来源于stack exchange,提问作者Syed Abdullah Saad
相关产品推荐
相关产品推荐

