携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第7天,点击查看活动详情
1. 引言
接着上一节中,接下来我们继续Ts中等篇的题型练习
https://github.com/type-challenges/type-challenges/blob/main/README.zh-CN.md 提供的TypeScript 类型体操姿势合集题型,目的是为了让大家更好的了解TS的类型系统,编写自己的类型工具,或者单纯的享受挑战的乐趣!
2. 题型
- Zip: 在这个挑战中,你应该实现一个类型<T, U> T和U必须是Tuple
type exp = Zip<[1, 2], [true, false]> // expected to be [[1, true], [2, false]]
思路: 总的思路就是先使用infer 关键字解构,在使用递归的思路处理该问题;当Demo,Demo4实例在T 是否属于[infer M,...infer N] 中就可过滤掉,其中有一点需要注意,当Demo3 中T和U的长度不一致时候会因为T 为前置判断,U中超出部分会自动过滤;完成。 解答:
type Zip<T extends any[],U extends any[]> = T extends [infer M,...infer N] ?
U extends [infer Z,...infer B] ? [[M,Z], ...Zip<N, B>] : [] : []
type Demo = Zip<[1, 2], [true, false]> // type Demo = [[1, true], [2, false]]
type Demo2 = Zip<[], []> // type Demo2 = []
type Demo3 = Zip<[1, 2, 3], ['1', '2']> // type Demo3 = [[1, "1"], [2, "2"]]
type Demo4 = Zip<[], [1, 2, 3]> // type Demo4 = []
type Demo5 = Zip<[[1, 2]], [3]> // type Demo5 = [[[1, 2], 3]]
- IsTuple:实现一个类型IsTuple,它接受输入类型T并返回T是否是元组类型。
type case1 = IsTuple<[number]> // true
type case2 = IsTuple<readonly [number]> // true
type case3 = IsTuple<number[]> // false
思路: 首先解题之前要明确:number[]是数组,[any] 这样的才是元组; 元组和数组是有区别的,他们的区别在于:
- 元组和数组的长度是有区别的:元组的长度是有限的,数组的长度是无限的,所以他们的['length']是有区别的;
- ['length']的区别:元组返回的数字,数组返回的是 number;
接下来解题,依次判断是否为never 空元组,是否为任意any[]数组;在判断长度是否为number 如果是的话就为数组返回false; 解答:
type IsTuple<T> = [T] extends [never]
? false
: T extends readonly any[]
? number extends T['length']
? false
: true
: false
- Chunk:你知道lodash吗?Chunk是一个非常有用的函数,现在让我们来实现它。Chunk<T,N>;接受两个必需的类型参数,T必须是元组,N必须是整数>=1
type exp1 = Chunk<[1, 2, 3], 2> // expected to be [[1, 2], [3]]
type exp2 = Chunk<[1, 2, 3], 4> // expected to be [[1, 2, 3]]
type exp3 = Chunk<[1, 2, 3], 1> // expected to be [[1], [2], [3]]
思路: 使用一个新增的参数C用来记载Chunk 内容,通过C['length'] extends N 来判断是否达到要求数量,当达到数量时就释放;如果是就把它放到数组里,继续递归后续内容,等待返回结果,没有的话就继续往这个临时参数C中添加新的元素,作为新值继续执行递归知道达到目标值为止; 解答:
type Chunk<T extends any[], N extends number = 1, C extends any[] = []> =
T extends [infer R, ...infer U]
? C['length'] extends N
? [C, ...Chunk<T, N>]
: Chunk<U, N, [...C, R]>
: C extends []
? C
: [C]