前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库GraphQL interface union 区别
APAPI 设计GraphQL

GraphQL 的 Interface 与 Union 类型在语义和使用场景上有什么区别?

GraphQL 的 Interface 约束共享字段,支持直接查询公共属性;Union 是异构集合,字段交集为零,必须用片段选取。选型取决于客户端是否需要统一字段。

前端进阶之旅 · 一题精讲更新于 2026.09.05
API 设计#GraphQL
先看核心答案
理解线索

抽象类型两分支

  1. Interface:共享字段要求实现类型必须包含这些字段
  2. Union:纯集合成员无共同字段,需片段选择
  3. 查询片段匹配用__typename或内联片段区分

当查询需要公共字段时用Interface,否则用Union。

核心回答

先记住这个答案

Interface 定义一组必须字段,所有实现该接口的类型都必须包含这些字段,因此若客户端只需公共字段,可直接选择,无需关心具体类型。Union 只列出可能成员类型,不声明任何共享字段,所以查询时必须用内联片段按具体类型选择字段。当多个类型有相同且稳定的字段时用 Interface;当类型之间无重叠且需要独立展示时用 Union。服务端通过 resolveType 或元数据判断实际类型。

  • Interface 共享公共字段,Union 全无共享字段
  • 查询公共属性用 Interface,异构展示用 Union
  • Union 必须为每个成员写内联片段

机制差异:字段约束与类型解析

GraphQL 的 Interface 类型要求所有实现它的对象类型必须包含它声明的全部字段。在 SDL 中,interface Node { id: ID! } 之后,任何 type User implements Node 都必须定义 id。因此,当查询返回类型是 Node 时,客户端可以直接选择 id,不需要知道返回的是 User 还是 Post。Union 类型则不同,它仅列出可能出现的对象类型,并不定义任何公共字段。例如 union Media = Image | Video,但 Image 和 Video 共享 url、size 等字段也必须在各自类型里重复,而查询 media 字段时必须写成 ... on Image { url } 这样的内联片段,不能直接 media { url }。

从执行器的角度看,二者都依赖 __typename 或服务端的 resolveType 方法确定具体对象,但 Interface 允许查询书在 schema 验证阶段就知道有个统一入口放子字段,而 Union 没有这个入口。也就是说,凡是需要从不同对象里提取同名字段的场景,Union 迫使客户端对每个对象复制一遍选择集,而 Interface 只需一次。这是二者最直观的工程差异。

搜索结果的异构返回

例如构建一个搜索接口,返回结果可能是文章、作者和话题。文章有 title、publishedAt;作者有 nickname、followers;话题有 topicName、count。三个类型有各自属性和字段名,不具统一的展示字段。当客户端只想渲染一个混合列表时,可选方案是定义 union SearchResult = Article | Author | Topic,查询中必须写三段行内片段去取各自的标签和元信息,组件中也要按 __typename 做 if/else。

如果产品又决定为所有搜索结果展示 breadcrumb 和 summary 两个公共字段,并希望客户端统一调用,那么更合适的做法是定义 interface SearchHit,并让三个类型都实现它。客户端可直接写 search { hits { breadcrumb summary } },一旦新类型加入,只要也实现该接口就不会破坏查询。但这个前提是公共字段长期稳定;若未来引入一个没有任何标题或摘要的‘算法解释’类型,就无法实现该接口,此时被迫改成 Union 或将接口字段设为 nullable,造成类型语义被扭曲。

字段变化与抽象选择

最典型的选择误区是看见多个类型有少数同名字段就立刻用 Interface,忽视这些字段未来可能被移除或变型。比如 content 字段在文章里是正文,在问题里是标题加详情,强行统一成字符串会丢失类型细节。另一方面,若只是临时有几个相同字段,用 Union 并让客户端用 ... on TypeA { commonField } 这样重复写,虽然啰嗦但能保持各类型独立演进。

还需要注意 Union 的成员只能是具体对象类型,不能是 Interface 或另一个 Union。因此无法通过将多个 Interface 作为成员来构造抽象。为了兼顾公共字段和异构扩展,常见手法是同时导出 Interface 和 Union,但 Union 的成员仍然需是对象类型;客户端若要公共字段就用 Interface 片段,若需要完整分支则用 Union。这种写法增加了 schema 的层级,也要求客户端正确选择片段,否则无法获得类型信息。

回答前,多想一步

容易答错的地方

Union 也有共享字段
错误认为 Union 成员可以像接口一样定义公共字段。实际上 GraphQL 规范规定 Union 不提供任何字段定义,客户端不能直接选择 Union 上的字段,必须用内联片段挨个成员选择。若确实有公共字段,应使用 Interface 而不是 Union。
Interface 只能用于同一继承链
误解 Interface 必须映射领域模型的继承。实际上 GraphQL Interface 只是结构约束,任何对象只要包含接口所列字段即可实现,不要求后端类有父子关系,因此它适合表达行为能力而非领域归类。
试着用自己的话回答

面试官还会怎么问?

服务端如何判断具体类型?

对于 Union 或 Interface,解析器可返回对象后由框架调用 resolveType,也可依赖 __typename 返回的字符串。实际开发中由解析函数决定是否额外实现 resolveType;通常使用对象的 type 字段或 constructor.name。

一个类型能同时实现多个 Interface 吗?

可以。对象类型可以实现多个 Interface 以表达多重能力,查询时可通过不同 Interface 的名称用片段访问各自字段,服务端执行器会按需并行解析。

字段重叠很多,但有个别特殊类型怎么办?

优先用 Interface 承载主要公共字段,再单独用 Union 包装那些不满足接口的异构类型,或者将特殊类型改为 nullable 字段补齐,但必须评估破坏性改动成本。

从一道题,走向一组知识

把知识连起来

GraphQL

GraphQL 中 Enum 适合建模什么,哪些情况应避免使用 Enum?

同属「GraphQL」专题,接着看 GraphQL enum 适用场景 演进 在具体场景中的处理方式。

GraphQL

GraphQL 中如何定义和使用自定义标量类型(如 DateTime)?

同属「GraphQL」专题,接着看 GraphQL custom scalar DateTime 序列化 在具体场景中的处理方式。

参考资料

  • Schemas and Types

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 机制差异:字段约束与类型解析
  3. 搜索结果的异构返回
  4. 字段变化与抽象选择
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑