Apollo Server中GraphQL Union类型返回列表时自定义Error的问题
解决Apollo Server联合类型返回列表时的鉴权错误问题
这个问题的核心在于GraphQL联合类型(Union)的设计限制以及你最初的Schema定义与返回值的矛盾,我来一步步帮你理清并解决:
问题根源分析
第一种Schema的问题:你定义
getReports返回[getReportUnion]!,这要求必须返回一个数组,数组中的每个元素是Error或getReportResult。但鉴权失败时你返回的是单个Error对象,不是数组,所以GraphQL会抛出Expected Iterable错误——它期待一个可迭代的数组,但你给了单个对象。第二种Schema的问题:你尝试把联合类型定义为
Error | [getReportResult],但GraphQL的联合类型只能包含命名的对象类型,不能直接包含列表(数组)类型,这种写法本身就是不合法的。
可行解决方案:用包装对象调整联合类型结构
我们需要重新设计Schema,让联合类型的成员都是对象类型,其中一个对象用来包装成功时的列表数据,另一个是错误类型。
步骤1:修正Schema定义
type Query { getReports(id: ID!, patient_id: Int): ReportResponseUnion! } # 联合类型:要么返回错误,要么返回包含报告列表的成功响应 union ReportResponseUnion = Error | ReportSuccessResponse # 成功响应:包装报告列表 type ReportSuccessResponse { reports: [getReportResult!]! } # 原有的报告结果类型 type getReportResult { id: ID! patient_id: Int! date: String! # 匹配你查询中用到的字段 } # 错误类型保持不变 type Error { error: Boolean! message: String! }
步骤2:调整Resolver逻辑
确保鉴权失败和成功时都返回符合联合类型要求的对象,并带上正确的__typename:
getReports: async (parent: any, args: any, context: any, info: any) => { const { id, patient_id } = args; const { isAuth, userId } = context.Auth; // 鉴权失败:返回Error类型对象 if (!isAuth || userId !== id) { return { __typename: "Error", error: true, message: "鉴权失败,请检查用户ID或JWT Token是否有效" }; } // 鉴权通过:获取数据并返回包装后的成功响应 const reportData = await /* 你的数据查询逻辑 */; return { __typename: "ReportSuccessResponse", reports: reportData // 这里是getReportResult类型的数组 }; }
步骤3:更新查询语句
对应调整查询,从成功响应中取出嵌套的reports列表:
query { getReports(id: "5f449b73e2ccbc43aa5204d88", patient_id: 0) { __typename ... on ReportSuccessResponse { reports { patient_id date } } ... on Error { error message } } }
关键注意事项
- 必须给联合类型的返回值加上
__typename字段,Apollo Server需要这个字段来正确判断当前返回的是联合类型中的哪一种对象。 - 联合类型的成员只能是命名对象类型,不能是列表、标量或其他非对象类型,这是GraphQL的核心规则之一。
内容的提问来源于stack exchange,提问作者Ericgit
相关产品推荐
相关产品推荐

