前端进阶之旅前端进阶之旅
  • 基础篇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 schema 类型系统 SDL
APAPI 设计GraphQL

GraphQL 的 schema 与类型系统由哪些核心部分构成?

GraphQL schema 由六种命名类型与类型修饰符构成:Object、Scalar、Enum、Interface、Union、Input Object,外加 Query、Mutation、Subscription 三个根入口类型。

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

类型系统的分层记忆

  1. 叶子:Scalar 与 Enum解析为单值,查询中不能再有子选择集
  2. 结构:Object 与 InputObject 描述输出字段,Input 只用于参数
  3. 抽象:Interface 与 UnionInterface 契约公共字段,Union 仅列举可能类型

判断用哪类:要公共字段选 Interface,只列候选选 Union,入参必须用 Input 类型。

核心回答

先记住这个答案

GraphQL schema 用类型系统完整描述 API 能返回什么数据。核心是六种命名类型:Object 类型定义字段结构,Scalar 是叶子值如 String、Int、Boolean、ID、Float,Enum 枚举有限取值,Interface 定义公共字段契约,Union 表示几种类型之一,Input Object 专用于参数输入。字段可带参数,类型可用 ! 和 [] 修饰表示非空与列表。Query、Mutation、Subscription 是普通 Object 类型,只是被声明为查询、变更、订阅三个操作的入口。schema 可以用语言无关的 SDL 书写,请求到达后按 schema 校验并逐字段执行。

  • 六种命名类型加两种修饰符构成 schema
  • 根类型只是被指定为入口的普通 Object
  • Scalar 是查询叶子,Object 才可继续选择

类型系统如何把 API 能力描述成一张契约

schema 的本质是一份可校验的契约:服务端用它声明客户端能问什么,客户端据此预测响应形状。Object 类型是主体,每个字段标注输出类型,字段还可以声明参数,参数只能用输入类型。Scalar 是查询的终点,字段解析到标量就不能再向下选择;内置 String、Int、Float、Boolean、ID 之外可以自定义标量。

抽象类型解决多态:Interface 要求实现类型提供全部公共字段,查询可直接选公共字段,选特有字段需行内片段;Union 不共享字段,只声明可能是哪几种 Object。类型默认可空且单值,! 表示非空承诺,[] 表示列表,两者可组合成 [User!]! 这类精确语义。Enum 把字段取值收敛到有限集合,便于校验与文档化。

电商商品与搜索结果的建模决策

假设为电商 API 建模:商品有 id、name、price,图书额外有 author,家电额外有 warrantyMonths,搜索接口返回图书或家电。约束是前端搜索页只展示名称和价格,详情页才按类型渲染。决策:定义 interface Product { id: ID! name: String! price: Int! },Book 与 Appliance 实现它,search(keyword: String!): [Product!]! 返回接口列表。

结果:搜索页查询公共字段不需要类型分支,详情页用 ... on Book 选择特有字段。若改用 union SearchResult = Book | Appliance,搜索页连 name 都必须写行内片段,冗余且易错。这里的关键判断是:候选类型之间存在客户端稳定依赖的公共字段时选 Interface,否则才用 Union,字段非空标记则按数据库约束如实标注。

类型声明在哪些情况下会失效或误导

schema 只承诺形状不承诺实现质量:price: Int! 声明非空,但若 resolver 因下游故障返回 null,该字段错误会沿父级向上冒泡,可能把整个对象置空。类型系统也无法表达业务规则,比如“折扣价必须低于原价”仍需参数校验或服务层逻辑。把 SDL 当作完整真相是常见误判。

处理方式:对可能失败的字段避免滥用 !,让部分失败只影响局部而非整棵树;业务不变量写在 resolver 或服务层,schema 仅做结构校验。代价是非空减少后客户端必须处理更多 null 分支,TypeScript 生成类型出现更多可空字段。判断标准:该字段的值是否在所有故障路径下都能保证存在,不能就保持可空。

回答前,多想一步

容易答错的地方

认为 Query 和 Mutation 是特殊语法类型
根操作类型本质是普通 Object 类型,只是通过 schema 声明被指定为入口。其字段的解析、参数、非空规则与任何 Object 字段完全一致,也可以用 schema { query: MyQuery } 改名。
把 Input Object 与 Object 混用
输出用的 Object 类型不能直接作参数类型。参数必须用 Input Object 或标量、Enum,因为入参不允许循环引用且不需要接口、联合等多态能力,混用会在 schema 构建期直接报错。
试着用自己的话回答

面试官还会怎么问?

Interface 和 Union 怎么选?

候选类型有客户端需要直接访问的公共字段时用 Interface,公共字段可写在接口选择上;仅表示若干不相关类型之一时用 Union。Union 成员必须是 Object 类型,且选择任何字段都要行内片段。

自定义标量(如 DateTime)属于哪部分?

属于 Scalar 类型扩展,需要在 schema 中声明 scalar DateTime 并在实现侧提供序列化、解析值、解析变量字面量三个函数。它仍是查询叶子,不能携带子字段。

SDL 与 code-first 定义 schema 有差别吗?

产物等价,都是同一份可内省的 schema。SDL 语言无关、便于评审契约;code-first 用宿主语言构造类型,便于与代码同步。区别在开发流程而非类型系统能力。

从一道题,走向一组知识

把知识连起来

GraphQL

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

本文只给出选择线索,该题深入比较两种抽象类型的语义差异与适用场景

GraphQL

GraphQL 中非空标记与列表组合(如 [User]、[User!]、[User]!)各自表示什么含义?

正文提到 ! 与 [] 组合,该题逐种解释四种可空组合的确切含义

参考资料

  • Schemas and Types

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

本题目录
  1. 先记住这个答案
  2. 类型系统如何把 API 能力描述成一张契约
  3. 电商商品与搜索结果的建模决策
  4. 类型声明在哪些情况下会失效或误导
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

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

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