导读:本期聚焦于胡建平创作的《TypeScript高级类型有哪些?一文讲透常见高级类型与实战问题》,敬请观看详情。泛型、条件类型、映射类型这些TypeScript高级类型到底该怎么用?本文从底层原理出发,系统讲解交叉类型、联合类型、泛型约束、infer关键字、内置工具类型的实现思路,并结合日常开发中容易踩坑的场景给出示例代码。比如联合类型和交叉类型的区别、any与unknown的差异、如何用条件类型做类型分发、Partial和Readonly背后的映射语法是什么,看完这篇基本能解决大部分高级类型的疑问。

TypeScript的高级类型是区分初学者和进阶开发者的分水岭。基础类型只能描述简单的数据结构,而高级类型可以表达复杂的类型关系,实现类型层面的逻辑运算。这篇文章把常用的高级类型逐一拆解,并结合实际开发中容易混淆的问题给出分析。

TypeScript高级类型有哪些?一文讲透常见高级类型与实战问题

联合类型与交叉类型的本质区别

联合类型和交叉类型是两组最容易混淆的符号。|表示联合,含义是“或”,即变量可以是其中任意一种类型;&表示交叉,含义是“与”,即必须同时满足所有类型的约束。

很多人以为交叉类型就是取交集,这个理解不完全准确。对于对象类型来说,交叉更像是“合并”,把多个类型的属性叠加到一起。而对于字面量类型的交叉,结果往往是never,因为一个值不可能同时是两个不同的字面量:

type A = { name: string };
type B = { age: number };
type C = A & B; // 同时拥有 name 和 age

type L = 'a' & 'b'; // never,不存在这样的值

联合类型还有一个重要特性叫“分发”。当泛型参数是联合类型并被用在条件类型中时,条件类型会自动对每个成员分别计算,最后再把结果合并成联合类型。理解这一点是掌握条件类型的关键。

泛型与条件类型的进阶用法

泛型的核心作用是让类型变成“参数”,从而在类型层面复用逻辑。但很多开发者只停留在函数泛型的层面,实际上泛型约束、默认值、以及和条件类型配合才是真正的威力所在。

keyoftypeof是两个重要的类型运算符。keyof T获取某个类型的所有属性名组成的联合类型,typeof则可以从一个运行时的值反向推导出类型,这在给配置对象定义类型时特别实用。

条件类型的语法是T extends U ? X : Y,配合infer关键字可以在匹配的过程中“提取”出某个类型。比如内置的ReturnType就是用infer拿到函数的返回值类型:

type MyReturnType<T> = 
  T extends (...args: any[]) => infer R ? R : never;

function getUser() {
  return { id: 1, name: '张三' };
}

type User = MyReturnType<typeof getUser>; // { id: number; name: string }

再比如提取Promise内部的类型,也是同样的套路,用infer声明一个位置,让TypeScript自己去推断填充。掌握了infer,你会发现很多原来需要手动声明的类型都能自动推导出来。

需要注意的是,如果不想让条件类型发生分发,可以用方括号把T包起来:[T] extends [U] ? X : Y,这样即使传入联合类型也会作为整体参与判断,这在判断never时尤其重要,因为裸的never分发后结果是never,永远走不到任何分支。

映射类型与内置工具类型的实现原理

TypeScript内置了一批工具类型,比如PartialReadonlyPickRecord。它们的底层都是映射类型,语法是在方括号里用in遍历一个联合类型:

type MyPartial<T> = {
  [K in keyof T]?: T[K];
};

type MyReadonly<T> = {
  readonly [K in keyof T]: T[K];
};

type MyPick<T, K extends keyof T> = {
  [P in K]: T[P];
};

映射过程中还可以加修饰符的加减操作。TypeScript 4.1之后支持-readonly-?这样的语法,用来移除只读或可选标记。官方的Mutable类型就是这么实现的。

模板字面量类型也是映射类型的黄金搭档。配合infer和递归,可以实现诸如把下划线命名转驼峰、给对象的所有方法加上统一前后缀这类需求,这在编写类型安全的工具库时非常实用。

any、unknown与never的使用边界

这三个顶层和底层类型经常被混用。any会直接放弃类型检查,等于回到了JavaScript;unknown同样可以承接任意值,但使用前必须先收窄类型,因此是更安全的选择;never表示不存在的类型,常用于穷尽检查和表示永远不会返回的函数。

一个实用的技巧是在switch语句中利用never做穷尽校验。给default分支的变量赋值为never类型,一旦后续给枚举新增了成员而忘记处理,编译器会立刻报错,避免运行时遗漏分支。

type Shape = 'circle' | 'square';

function area(s: Shape) {
  switch (s) {
    case 'circle': return 1;
    case 'square': return 2;
    default:
      const _check: never = s; // 如果Shape新增成员,这里会报错
      return _check;
  }
}

总结一下学习路径:先把联合、交叉、泛型约束这些基础打牢,再攻克条件类型和infer,最后研究映射类型和模板字面量类型的组合运用。高级类型写多了你会发现,类型系统本身就是一门小型的函数式编程语言,掌握它的思维方式,比背下所有工具类型的用法重要得多。

TypeScript高级类型泛型修改时间:2026-09-11 15:36:32

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260911/54749.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。