JavaScript 中的类型体操:TypeScript 高级类型(Conditional Types, Mapped Types)

JavaScript 类型体操:TypeScript 高级类型,让你的代码像太极一样优雅!

各位观众,晚上好!欢迎来到今天的 "TypeScript 类型体操" 讲座。今天,我们不谈枯燥的类型定义,而是要让大家感受一下类型系统的力量,就像练太极一样,四两拨千斤,用看似简单的技巧,解决复杂的问题。 准备好了吗?让我们一起走进 TypeScript 高级类型的世界,体验一下类型体操的魅力!💪

一、开场:什么是类型体操?为什么要练?

你可能会好奇:什么是“类型体操”?听起来像某种健身运动。没错,它确实是一种“健身运动”,只不过锻炼的是你的大脑,提升的是你的类型编程能力。

简单来说,类型体操就是利用 TypeScript 提供的各种高级类型特性(比如 Conditional Types, Mapped Types, etc.)来玩转类型,对类型进行转换、计算、推断,最终得到我们想要的类型结果。

为什么要练?

  • 提升代码质量: 更精确的类型定义可以避免运行时错误,让你的代码更加健壮。
  • 增强代码可读性: 通过清晰的类型定义,可以让其他人更容易理解你的代码意图。
  • 提高代码复用性: 通过泛型和类型体操,可以编写更通用、更灵活的代码。
  • 解锁高级框架和库的源码: 许多流行的前端框架和库,比如 React、Vue、Angular,都大量使用了 TypeScript 高级类型。掌握类型体操,才能更好地理解它们的源码,甚至参与贡献。
  • 面试加分项: 毫不夸张地说,掌握类型体操,是高级前端工程师的必备技能。面试官会通过考察你对类型体操的理解,来判断你对 TypeScript 的掌握程度。

总之,类型体操就像武林秘籍,练成之后,不仅可以让你在代码世界里更加游刃有余,还能让你在面试场上脱颖而出!😎

二、热身:回顾 TypeScript 基础类型

在开始高难度动作之前,我们需要先热身一下,回顾一下 TypeScript 的基础类型:

  • boolean 布尔值,truefalse
  • number 数字,包括整数和浮点数。
  • string 字符串。
  • null 空值。
  • undefined 未定义。
  • symbol ES6 新增的原始数据类型,表示独一无二的值。
  • object 对象。
  • array 数组。
  • tuple 元组,固定长度和类型的数组。
  • enum 枚举,一组命名的常量。
  • any 任意类型,放弃类型检查,尽量避免使用。
  • unknown 未知类型,比 any 更安全,需要进行类型断言或类型收窄才能使用。
  • void 没有返回值。
  • never 永远不会到达的类型,通常用于抛出异常或无限循环的函数。

这些基础类型就像我们练武的基本功,只有打好基础,才能更好地学习高级类型。

三、正餐:Conditional Types(条件类型)

现在,让我们进入今天的正餐:Conditional Types(条件类型)。条件类型就像编程界的“如果…那么…否则…”语句,可以根据不同的类型条件,返回不同的类型结果。

1. 基本语法:

T extends U ? X : Y
  • T extends U:判断类型 T 是否可以赋值给类型 U
  • ? X:如果 T extends U 为真,则返回类型 X
  • : Y:如果 T extends U 为假,则返回类型 Y

2. 示例:判断类型是否为 string

type IsString<T> = T extends string ? true : false;

type Result1 = IsString<string>; // true
type Result2 = IsString<number>; // false

在这个例子中,IsString<T> 接收一个类型参数 T,如果 T 可以赋值给 string,则返回 true,否则返回 false

3. infer 关键字:类型推断的利器

infer 关键字是条件类型中最强大的工具之一,它可以用来推断类型。

示例:获取数组元素的类型

type ElementType<T> = T extends (infer U)[] ? U : never;

type Result3 = ElementType<number[]>; // number
type Result4 = ElementType<string>; // never

在这个例子中,ElementType<T> 接收一个类型参数 T,如果 T 是一个数组类型,则使用 infer U 推断数组元素的类型,并将推断结果赋值给 U,然后返回 U。如果 T 不是一个数组类型,则返回 never

4. 分布式条件类型(Distributive Conditional Types)

当条件类型中的类型参数是一个联合类型时,TypeScript 会将条件类型应用到联合类型的每个成员上,然后将结果组合成一个新的联合类型。

示例:从联合类型中排除 nullundefined

type NonNullable<T> = T extends null | undefined ? never : T;

type Result5 = NonNullable<string | number | null | undefined>; // string | number

在这个例子中,NonNullable<T> 接收一个类型参数 T,如果 Tnullundefined,则返回 never,否则返回 T。当 Tstring | number | null | undefined 时,TypeScript 会将条件类型应用到每个成员上:

  • string extends null | undefined ? never : string => string
  • number extends null | undefined ? never : number => number
  • null extends null | undefined ? never : null => never
  • undefined extends null | undefined ? never : undefined => never

然后将结果组合成一个新的联合类型 string | number | never | never,最终简化为 string | number

表格总结:Conditional Types 的关键点

| 特性 | 描述 | 示例

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注