TypeScript类型体操--Reverse、Filter、Flatten
大家好,我是苏先生,一名热爱钻研、乐于分享的前端工程师,跟大家分享一句我很喜欢的话:人活着,其实就是一种心态,你若觉得快乐,幸福便无处不在
github与好文
前言
前边三篇文章我们一共实现了26个工具类型,按照本专栏的规划,还差73个...
本节我们继续学习元组相关的类型编程
提示
对于语法层面的知识点本系列(类型体操开头的标题)不会展开说明哈,可以自行搜索学习其他大佬的优质文章或者等我后续更新补充
Reverse
- 功能
将数组类型中的元素进行翻转
- 实现
首先,它接收一个泛型参数T
type Reverse<T>
对于该泛型参数,我们需要对其进行约束,使其必须是数组类型
T extends any[]
接着,我们要想办法拿到数组中的单个元素,根据前两篇文章的学习,我想聪明的你已经知道了,使用扩展运算符取余并重新构建一个数组可以做到
[infer F,...infer R]
此时,显而易见的是,只需要对R和F进行位置调换就可以使得元素F位置被调整
[...R,F]
那么以此类推,让剩余元素R递归下去就能求出结果,最终实现如下
type Reverse<T extends any[]> = T extends [infer F,...infer R] ? [Reverse<R>,F] : T
- 使用示例
Filter
- 功能
从数组类型中挑选指定的类型并返回一个由挑选类型组成的新数组
- 实现
首先,它接收两个泛型参数T,U
type Filter<T,U>
对于参数T,需要进行约束,使其必须为数组类型,至于参数U则为any类型
type Filter<T extends any[],U>
同样的我们通过重新构造数组的方式,获取到数组中的每一个元素,并利用infer保持其类型不变
[infer F,...infer R]
现在我们来对比当前元素F与泛型U之间的关系,如果F是被过滤元素集合中的一员,则它们之间一定存在着协变关系,那么我们就可以通过extends来判断是否具有父子关系来做相应的处理了
F extends U ?'进行下一轮比较' : ?
相信经过前边十几个数组相关的练习,你应该也想到了,没错,就是递归。如下,如果找到了,就保留,没有就过滤掉,并使用R进行下一轮的筛选
F extends U ?[F,...Filter<R,U>] : Filter<R,U>
因此,我们的最终实现版本如下
type Filter<T extends any[],U> = T extends [infer F,...infer R] ?
F extends U ?
[F,...Filter<R,U>]
:Filter<R,U>
:[]
- 使用示例
Flatten
- 功能
扁平化数组
- 版本一
他接收一个泛型参数T,并且为数组类型
type Flatten<T extends any[]>
通过extends构造条件语句,使用infer推断类型
T extends [infer F, ...infer R]
对于此时得到的F和R,R确定为数组类型,F不确定,因此对F进行条件判断
F extends any[]
如果F是一个数组类型,则将F和R丢给Flatten继续递归
[...Flatten<F>,...Flatten<R>]
否则仅递归求R即可
[F, ...Flatten<R>]
至于T的非数组类型,我们将其包装成数组返回即可
[T]
故,完整实现如下
type Flatten<T extends any[]> = T extends [infer F, ...infer R]
? F extends any[]
? [...Flatten<F>,...Flatten<R>]
: [F, ...Flatten<R>]
: [T]
- 版本二
版本一的实现能将数组T的成员拍平,但是会产出冗余的代码,如下,多出来了N个空数组
这主要是因为在对最后一个成员进行处理时,R是一个空数组,当进行下一次递归时将R传递给Flatten后会取到[T],故我们需要对空数组进行单独处理,修改后的代码如下
type Flatten<T extends any[]> = T extends [] ? [] : T extends [infer F, ...infer R]
? F extends any[]
? [...Flatten<F>,...Flatten<R>]
: [F, ...Flatten<R>]
: [T]
- 使用示例
下期预告
FlattenDepth
- 功能
允许对数组按指定的深度进行拍平
- 使用示例
type a = FlattenDepth<[1, 2, [3, 4], [[[5]]]], 2> // [1, 2, 3, 4, [5]]
如果本文对您有用,希望能得到您的点赞和收藏
订阅专栏,每周更新1-2篇类型体操,每月1-3篇vue3源码解析,等你哟😎
转载自:https://juejin.cn/post/7252526727607124027