likes
comments
collection
share

全面解析 TypeScript 泛型的二三事2024年了相信大家都已经在日常开发的过程中使用上了 TypeScript

作者站长头像
站长
· 阅读数 16

2024年了相信大家都已经在日常开发的过程中使用上了 TypeScript 了。TypeScript 增强了代码可靠性和可维护性,确保减少运行时错误并提高开发人员的工作效率。

TypeScript 通过类型声明 使得 javascript 拥有了强类型校验。而泛型的是类型声明中最重要的一环,通过运用 泛型, 可以让我们更好地扩展类型声明。

今天我们来分析一下 TypeScript 泛型。

什么是泛型

我们先来看一下真实的仓库里面写的一个泛型带来的压迫感吧(hhhh)

全面解析 TypeScript 泛型的二三事2024年了相信大家都已经在日常开发的过程中使用上了 TypeScript

第一眼看上去感觉东西很多,,,不知道从哪里看过来

说回来,泛型简单来说(Generics)是一种可以使类、接口和函数能够处理不同类型的方式,而不需要明确指定具体的类型。

TypeScript 中,泛型通过在类、接口和函数的声明中引入类型变量来实现。

这里我们可以看一个函数定义泛型的示例:

全面解析 TypeScript 泛型的二三事2024年了相信大家都已经在日常开发的过程中使用上了 TypeScript

红色的方框:定义的泛型类型 SomeType

黄色的方框:使用泛型SomeType来约束函数的参数是 SomeType类型数组

绿色的方框:约束函数的返回值为 泛型 SomeType 本身

需要注意的是,泛型本身不是 TypeScript 类型,而是类型参数,即调用函数时将指定的类型的占位符。

对于泛型的命名,可以将其命名为任何您想要的名称(只要它不是保留关键字(例如 constenum)或已导入的类型名称)。一般我们经常使用单个字母来表示泛型,例如 T

其实可以简单理解为 泛型 是一种 类型的占位

定义泛型

函数参数的泛型定义

全面解析 TypeScript 泛型的二三事2024年了相信大家都已经在日常开发的过程中使用上了 TypeScript

在函数中使用泛型,常用于约束函数参数的类型。需要注意的是函数参数的泛型定义和调用都是定义在函数参数列表的括号前

我们还可以定义多个泛型,只要通过 , 进行分隔就行

全面解析 TypeScript 泛型的二三事2024年了相信大家都已经在日常开发的过程中使用上了 TypeScript

接口 Interface 的泛型定义

接口的泛型定义的位置是紧跟在接口名称后面

全面解析 TypeScript 泛型的二三事2024年了相信大家都已经在日常开发的过程中使用上了 TypeScript

当泛型在使用的时候,指定了具体的类型之后,我们就不能违背这个类型,否则会触发 TypeScript 编译错误的提示

全面解析 TypeScript 泛型的二三事2024年了相信大家都已经在日常开发的过程中使用上了 TypeScript

类型别名 type 的泛型定义

同样的类型别名也可以通过定义泛型来扩大自己的类型声明范围。类型别名定义泛型的位置和接口 Interface 定义的方式是一致的

全面解析 TypeScript 泛型的二三事2024年了相信大家都已经在日常开发的过程中使用上了 TypeScript

Class 的泛型定义

类定义泛型是在 类名 后面,如果是匿名类的话,就是直接定义在 class 后面。

全面解析 TypeScript 泛型的二三事2024年了相信大家都已经在日常开发的过程中使用上了 TypeScript

全面解析 TypeScript 泛型的二三事2024年了相信大家都已经在日常开发的过程中使用上了 TypeScript

泛型的约束

泛型通过 extend 关键字实现泛型的约束,就是在一些场景下,你知道这个泛型的类型不确定,但是你知道这个类型一定有一些固定的属性,或者一定是属于某一个基础类型,这时候我们可以使用泛型约束,确保传递的参数一定具有某个属性或者属于某一种类型,这样就能安全地在 函数体内执行相关的属性或方法

全面解析 TypeScript 泛型的二三事2024年了相信大家都已经在日常开发的过程中使用上了 TypeScript

如果我们传递的类型不满足约束条件时, TS 就会在运行的阶段会提示我们,这样可以避免我们产生后续的 bug

全面解析 TypeScript 泛型的二三事2024年了相信大家都已经在日常开发的过程中使用上了 TypeScript

泛型的默认类型

泛型的默认类型和参数的默认类型一样,也是通过 = 来声明一个泛型的默认类型

全面解析 TypeScript 泛型的二三事2024年了相信大家都已经在日常开发的过程中使用上了 TypeScript

使用默认类型,可以让我们在调用的时候,如果不传递类型给泛型,泛型也能获取到默认类型应用到具体的变量约束上。

infer 在泛型中的应用

在泛型中,我们经常会使用 infer 对泛型做进一步的类型推定, 进一步将范围进行缩小,推断到我们想要的类型。

这里我们可以看一下 内置的 ReturnType 的实现

全面解析 TypeScript 泛型的二三事2024年了相信大家都已经在日常开发的过程中使用上了 TypeScript

在这个示例中,ReturnType 是一个条件类型,它检查类型 T 是否符合函数类型 (...args: any[]) => infer R。如果 T 是一个函数类型,TypeScript 会推断出函数的返回类型 R

infer 目前只能在 extends 的条件语句中

内置的泛型工具函数

TS 内置了很多工具函数,具体可以查看官方文档关于Utility Types 部分

Partial

将类型 T 的所有属性变为可选属性。

全面解析 TypeScript 泛型的二三事2024年了相信大家都已经在日常开发的过程中使用上了 TypeScript

  • keyof T 获取类型 T 的所有属性名。
  • [P in keyof T] 是一个映射类型,它遍历 T 的所有属性名。
  • T[P] 获取属性名 P 对应的属性类型。
  • ?: 将属性变为可选属性。

Required

将类型 T 的所有属性变为必选属性。

全面解析 TypeScript 泛型的二三事2024年了相信大家都已经在日常开发的过程中使用上了 TypeScript

  • keyof T 获取类型 T 的所有属性名。
  • [P in keyof T] 是一个映射类型,它遍历 T 的所有属性名。
  • T[P] 获取属性名 P 对应的属性类型。
  • -? 移除可选属性修饰符 ?,将属性变为必选属性。

Readonly

将类型 T 的所有属性变为只读属性。

全面解析 TypeScript 泛型的二三事2024年了相信大家都已经在日常开发的过程中使用上了 TypeScript

  • keyof T 获取类型 T 的所有属性名。
  • [P in keyof T] 是一个映射类型,它遍历 T 的所有属性名。
  • T[P] 获取属性名 P 对应的属性类型。
  • readonly 将属性变为只读属性。

小结

泛型作为 ts 中重要的基石的存在,学会了 泛型的使用,可以让我们编写更加健壮且可维护的代码

如果这篇文章对你有帮助,欢迎点赞、关注、转发!

转载自:https://juejin.cn/post/7388066315502895139
评论
请登录