TS 泛型的使用
大纲链接 §
[toc]
简单的泛型 Generic Types
⇧
一般类型(非泛型)的局限 V.S. 泛型的作用 ⇧
有一个直接返回参数的函数
|
|
- 以上的函数不能表示 参数类型需要与返回值类型相同的情况
使用泛型
|
|
- 泛型 可以理解为 不定类型,用来表示多种类型
- 将泛型的类型
string
代入就可得到s
的类型 - 一旦确定类型,将不同类型重复赋值相同变量名,也会类型报错
- 可以使用任意大写字母表示,一般使用尖括号来声明
<T>
,在冒号后像类型一样使用
返回数组类型的例子 ⇧
|
|
不推荐的写法 ⇧
|
|
<T>(arg: T) => T
和 函数中的类型声明<T>(arg: T): T
等价
区别于类型断言 ⇧
类型断言,在编译时起作用
- “尖括号” 用法
|
|
as
语法
|
|
泛型常用组合形式 ⇧
- 泛型 + 接口
interface x<T> {(a: T): T;}
- 使用
let xxx: x<string> = (a) => a;
- 泛型 + 类型别名
type t<T> = {a: T;}
- 多个泛型
type t<T, P> = {a: T; b: P}
- 泛型 + 函数
function fn<T>(arg: T): T {}
- 泛型 + 类
class C<T> {attr: T; fn: (a: T) => T }
- 使用
let cc = new C<string>()
- 约束 构造函数/类
new(): T
JS
工厂函数function create(C) {return new C()}
- 使用泛型
function create<T>(C: {new (): T): T { return new C()}
- 表示 实例对象的类型 为
T
;传递的参数为一个 类C
|
|
泛型就像函数 ⇧
|
|
语法 ⇧
区别项 \ 类比项 | 名称 | 参数列表 可传默认项 | 主体 | 调用 | 返回项 |
---|---|---|---|---|---|
函数 | 函数名 | 形参/实参 (默认值) | 函数体 | 函数调用 | 返回值 |
泛型 | 具名:类型别名/接口等 匿名:函数/类等 | 泛型参数 / 代入具体类型 (默认类型) | 类型主体(包含属性类型声明、类型集合、集合运算等逻辑) | 类型调用 | 返回新的类型 |
泛型是面向对象的经典概念之一 ⇧
- 泛型,即“参数化类型”,也是一种类型
- 泛型是一种接受其他类型的类型
- 也称为泛型函数
|
|
- 泛型:未被声明具体类型的类型(类似
unknown
),type X<T> = T extends unknown ? T : never
- 可以理解为类型的占位符
- 函数的本质是:
- 延后执行 一段逻辑,之前学过函数调用的时机,声明和执行分离
- 部分待定的代码作为参数,调用时才填入具体值
- 类比泛型
- 延后声明 具体类型,先用占位符表示,之后使用到时再替换为具体类型
- 部分待定的类型作为参数,调用时才填入具体类型
|
|
- 具体代码:码上掘金,鼠标滑过类型查看类型提示
- 以函数形参来类比泛型,实参就可以理解为:为泛型明确声明具体类型,可称为泛型的类型收窄
为什么会有泛型 ⇧
- 弱类型语言不需要泛型,比如
JS
- 具有复杂的类型系统的计算机语言需要泛型,比如
JAVA
|
|
- 判断分支代码无法实现以一对应,存在类型不精确或错乱的情况
|
|
- 如果参数的类型和返回的类型有特殊的要求,比如一一对应,就需要泛型
- 判断分支代码无法实现以一一对应,存在类型不精确或错乱的情况
- 没有泛型,就无法实现复杂的逻辑需求
- 没有泛型的类型系统,就如同没有函数的编程语言
一星难度的 TS
体操:代入法 ⇧
|
|
- 鼠标悬浮的提示无法知道详细类型
- 可使用代入法理解
- 无需逻辑操作
可传类型默认值
|
|
二星难度的 TS
体操:条件类型 ⇧
补全类型
- 提示:使用条件类型
Conditional Types
,即三元表达式 - 提示:类型的 关系运算符 只有一种:
extends
意为包含于,表示类型集合的从属关系
|
|
- 集合的关系判断无法像值那样,有大于小于或相等的判断,只有从属关系的判断
- 集合范围决定了是否为从属包含关系,范围完全一样的是一种特殊的情况
extends
读作 “包含于”,而不是面向对象中的继承
|
|
条件类型的特殊情况 never
⇧
never
可理解为空集,但在类型判断中,存在特殊情况
|
|
规则
- 若
<T>
为联合类型,则各个类型,分开计算 - 若
<T>
代入never
,则表达式的值为never
|
|
- 联合类型的条件判断,分开计算可以理解为 进行类型收窄时的处理过程
|
|
- 空集没有元素,直接返回
never
使用类比来理解
- 泛型 + 联合类型,比作乘法的 分配律
(A | B) extends X -> A extends X | B extends X
never
比作乘法中的0
- 只对泛型有效
在泛型中使用 extends
泛型约束 ⇧
- 给泛型添加类型约束,缩小泛型的范围
- 关键字
extends
,翻译为包含于(集合范围小于或等于),区别于类class
的继承关键字
|
|
- 声明的泛型
<T>
必须满足 包含于HasLength
接口
在泛型中使用 keyof
⇧
在泛型中使用 extends keyof
⇧
泛型的实际使用:在React
中使用泛型 ⇧
- 安装
react
和react-dom
- 安装
@types/react
和@types/react-dom
Ctrl + 点击
查看泛型是什么,使用代入法
|
|
泛型 区别于 函数重载 ⇧
- 泛型:使用时声明具体类型类型
- 难以根据不同条件,约束所有参数的类型
- 函数重载:根据参数类型条件判断
- 支持多种属性签名
|
|
- 让函数满足多种的参数条件就是函数重载
如何用泛型封装网络请求库 ⇧
- 使用
axios
时 可以根据参数的类型,来自动判断执行的逻辑分支axios.get('/url', {})
axios.get({url: '/xxx', header: ''})
axios.get(url?: string, options?: {url: string, header: unknown}): void
- 拿获取用户来举例
const user = createResource('/api/v1/user')
|
|
使用映射类型 in
⇧
难度为三星的泛型类型体操 ⇧
如何使用 -readonly
⇧
类型体操有多难 ⇧
如何提问 ⇧
stackblitz.com
vanilla TS
- 需要默认导出任意
export {}
来消除报错
- 需要默认导出任意
- 码上掘金
- 将有疑问的代码在平台上运行,保存后分享路径
url
- 描述问题
参考文章 ⇧
相关文章 ⇧
- 作者: Joel
- 文章链接:
- 版权声明
- 非自由转载-非商用-非衍生-保持署名