GraphQL Nexus 含列表成员的Union类型实现咨询
问题解答
核心结论
你新增BookmarkSuccess对象类型包装书签数组的思路完全符合GraphQL规范,不需要做额外的特殊解析,只需要调整Union成员配置和查询返回结构即可。
问题原因
GraphQL 明确规定 Union 类型的成员只能是对象类型(Object Type),不支持直接将列表类型、标量类型作为Union成员,因此你最初期望的[Bookmark]! | NotAllowedError | NotFoundError | UnknownError写法本身不符合类型系统规则,必须通过对象类型包装数组字段。
具体实现步骤
- 调整Union类型定义,将原成员中的
Bookmark替换为BookmarkSuccess,同时补充resolveType逻辑,让GraphQL能识别返回结果对应的成员类型:const BookmarkResult = unionType({ name: 'BookmarkResult', definition(t) { t.members('BookmarkSuccess', 'NotAllowedError', 'NotFoundError', 'UnknownError') }, resolveType: (res) => { if ('bookmarks' in res) return 'BookmarkSuccess' if (res.errorType === 'NOT_ALLOWED') return 'NotAllowedError' if (res.errorType === 'NOT_FOUND') return 'NotFoundError' return 'UnknownError' } }) - 完成
BookmarkSuccess类型定义,bookmarks字段不需要手写resolve,GraphQL默认解析器会自动读取父对象上的同名属性:const BookmarkSuccess = objectType({ name: 'BookmarkSuccess', definition(t) { t.nonNull.list.nonNull.field('bookmarks', { type: 'Bookmark' // 无需自定义resolve }) } }) - 调整查询字段的resolve逻辑,成功分支将书签数组包装为带
bookmarks属性的普通对象即可,错误分支逻辑无需改动:const BookmarkQuery = queryField('links', { type: 'BookmarkResult', resolve: async () => await pipe( getAllBookmarks(), foldW( // 错误分支保持原有逻辑,直接返回错误对象 (err) => err, // 成功分支包装为BookmarkSuccess对应的结构 (bookmarks) => ({ bookmarks }) ) )() })
注意事项
- 如果你原来的代码用
of方法构造返回值,只需要把成功分支的of(bookmarks)改为of({ bookmarks })即可,其余逻辑无需调整。 - 必须为Union配置
resolveType,或在每个成员类型上配置isTypeOf判断逻辑,否则GraphQL运行时无法识别返回结果对应的Union成员,会抛出类型错误。
内容的提问来源于stack exchange,提问作者Joshua Richardson
相关产品推荐
相关产品推荐

