前端进阶之旅前端进阶之旅
  • 基础篇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 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库TypeScript infer 多候选 联合 交叉 最后重载
TyTypeScript类型运算

TypeScript 的 infer 有多个候选时为何得到联合或交叉,重载又为什么看最后签名?

出现多个类型并不只有一种原因:它可能来自结构中的多个位置,也可能来自联合分发或重载签名。

前端进阶之旅 · 一题精讲更新于 2026.09.06
TypeScript#类型运算#类型系统
先看核心答案读代码示例
理解线索

分别观察三种候选来源

  1. 结构位置同一个变量从多个字段或参数位置获得信息
  2. 联合分发不同成员分别进入条件后再合并结果
  3. 重载签名类型提取通常依据最后可见声明签名

以下是明确结构下的典型结果,复杂递归和特殊类型需要用当前编译器进一步核对。

核心回答

先记住这个答案

条件类型中的 infer 可以从匹配结构提取类型,同一个推断变量出现多个候选时,结果取决于候选位置和结构关系。典型输出位置的多个候选可能合并为联合,函数参数这类输入位置的候选可能形成交叉,以满足相应兼容要求。对重载函数提取返回类型时,通常从最后一个声明签名推断,并不会逐个模拟实际参数调用来选择最佳重载。还要把这些规则与条件类型对联合输入的分发分开分析,不能统一概括成 infer 总取联合或总取最后一个类型。

  • 先确定多个候选来自结构、分发还是重载
  • 输出与输入位置的候选合并方向可能不同
  • 重载类型提取不等于一次真实调用的重载选择

为什么输出候选可以合并为联合

一个对象的两个输出字段分别提供字符串和数字,用同一个 infer 变量描述它们时,联合可以容纳两种输出。若候选来自两个函数的输入位置,则需要考虑什么输入能同时满足相关处理能力,典型结果会表现为交叉约束。

示例分别提取字段值和函数输入,故意用两个不同对象结构作为输入候选,让交叉结果仍有可构造的意义。若直接使用互斥基础类型,交叉可能归约为 never,容易让读者只记住一个空结果而忽略背后的兼容关系。

不同位置中的候选合并TypeScript
type Values<T> = T extends { left: infer U; right: infer U } ? U : never;
type Inputs<T> = T extends {
  first: (value: infer U) => void;
  second: (value: infer U) => void;
} ? U : never;
type OutputChoice = Values<{ left: string; right: number }>;
type InputRequirement = Inputs<{
  first: (value: { id: string }) => void;
  second: (value: { name: string }) => void;
}>;
type CallResult<F> = F extends (...args: never[]) => infer R ? R : never;
declare function convert(value: string): number;
declare function convert(value: number): string;
declare function convert(value: string | number): string | number;
type OverloadResult = CallResult<typeof convert>;

OutputChoice 为 string | number,InputRequirement 同时要求 id 与 name。OverloadResult 根据最后的联合签名得到 string | number;声明函数这里只提供类型,不构成可直接运行的函数实现。

重载最后签名与实际调用不是同一过程

真实调用 convert 时,编译器会根据传入参数匹配可用重载;提取整个函数类型的返回类型时,并没有某组实际参数参与选择,因此不能期待它分别得到所有输入与输出的一一对应表。最后的宽签名通常承担概括可调用形态的角色。

如果最后一个公开重载只是某个窄分支,而没有概括所有分支的签名,提取结果也可能只反映那个窄返回类型。实现签名是否对外可见同样需要分清。库工具若依赖重载顺序,应通过消费端类型测试固定预期,避免调整声明顺序后静默改变结果。

复杂推断需要保留可解释性

联合输入可能先分发,再在每个成员内合并候选,最后又形成新的联合。调试时可以把工具拆成中间类型别名,逐步检查每一层结果。只看最终编辑器展开的大类型,往往难以判断是哪一种机制引入了某个成员。

函数属性、方法声明、any 和 never 都可能影响更复杂推断。不要把一个示例中的联合或交叉结论当作所有位置的定律。对公共工具应验证典型输入、冲突候选、重载顺序和特殊类型,必要时改用更明确的类型参数关系。

回答前,多想一步

容易答错的地方

infer 遇到多个类型总是生成联合
候选所处的位置和结构关系会影响合并方式,输入位置可能要求交叉;还需区分候选合并与条件类型本身的联合分发。
提取重载返回类型会自动执行最佳重载匹配
没有具体调用参数时,这不是一次普通重载调用,通常从最后声明签名推断;需要输入输出映射时应显式设计相应契约。
试着用自己的话回答

面试官还会怎么问?

两个输入候选是 string 和 number 会怎样?

在这种交叉要求下可能得到 never,因为没有正常值同时满足两者;应确认工具真的是在寻找共同输入,而不是想收集任一可能输入。

调整重载顺序会影响工具类型结果吗?

可能会,因为最后可见签名会影响推断,公开声明的顺序也因此属于可观察类型契约;修改后应验证消费端代表性用法。

如何避免复杂 infer 推断难以维护?

优先拆出清楚的中间类型,减少一层同时承担分发、过滤与候选合并的职责,并给重要结果写有意义的类型断言测试。

从一道题,走向一组知识

把知识连起来

泛型设计

TypeScript 怎样根据泛型参数的位置判断协变与逆变,in 和 out 需要手写吗?

先从生产与消费位置理解兼容方向

类型运算

TypeScript 条件类型为什么对联合分发,方括号怎样让它整体判断?

把候选合并与联合逐成员计算分成两个步骤

参考资料

  • TypeScript:Inferring Within Conditional Types
  • TypeScript 2.8:Conditional Types

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

本题目录
  1. 先记住这个答案
  2. 为什么输出候选可以合并为联合
  3. 重载最后签名与实际调用不是同一过程
  4. 复杂推断需要保留可解释性
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

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

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