持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第11天,点击查看活动详情
前言
在学习typescript的过程当中,有一个github库对其类型的学习特别有帮助,是一个有点类似于leetcode的刷题项目,能够在里面刷各种关于typescript类型的题目,在上一篇文章中,我们完成了中等的第四题,今天来做中等的第五题 10-medium-tuple-to-union
下面这个是类型体操github仓库:
10-medium-tuple-to-union
今天要来实现一个工具类型,将元组转为联合类型。
import type { Equal, Expect } from '@type-challenges/utils'
type cases = [
Expect<Equal<TupleToUnion<[123, '456', true]>, 123 | '456' | true>>,
Expect<Equal<TupleToUnion<[123]>, 123>>,
]
从测试用例和README能够清楚地知道,我们需要把元组中的元素拿出来,并且转为联合类型。
实现 TupleToUnion
infer 解法
对于数组来说,我们能够通过下标也就是数字索引来获取其中的属性:
type A1 = [1,2]
type A2 = A1[0]
// type A2 = 1
那么我们是否能够结合之前提过的 infer 关键字,能够通过 infer 和 rest 结合获取一个数组中的第一位和剩余位,这样一来,加上递归,就能够循环获取第一位,最后返回一个联合类型。
type TupleToUnion<T> = T extends [infer F, ... infer rest] ? F | TupleToUnion<rest> : never
type A1 = TupleToUnion<[1,2,boolean]>
// type A1 = boolean | 1 | 2
[key] 索引签名
我们能够通过索引签名的类型来获取索引签名的对应的类型:
type A1 = {
[key:string]:1|2|3
}
type A2 = A1[string]
// type A2 = 1 | 2 | 3
并且当我们查看数组的key值时,就会发现:
type A4 = [1,2,3,true]
type A3 = {[P in keyof A4]:A4[P]}
// type A3 = {
// [x: number]: true | 1 | 2 | 3;
// 0: 1;
// 1: 2;
// 2: 3;
// 3: true;
// length: 4;
// toString: () => string;
// toLocaleString: () => string;
// pop: () => true | 1 | 2 | 3 | undefined;
// push: (...items: (true | 1 | 2 | 3)[]) => number;
// ... 29 more ...;
// at: (index: number) => true | ... 3 more ... | undefined;
// }
数组中也存在着一个索引签名,它的类型是number,并且对应了数组中所有属性的联合类型,那么,我们就能够利用上面这种更简单的方法,来获取数组中所有属性类型的联合类型。
type TupleToUnion<T extends unknown[]> = T[number]
type A5 = TupleToUnion<['s',2,3]>
// type A5 = 3 | "s" | 2
知识点
关于上述提到了部分的知识点:
- infer 关键字
- rest 参数
- 索引签名
infer 关键字和 rest 参数我们之前都有做过相关的题目,不清楚的话可以回顾一下之前的简单题,这里就不在过多描述。
索引签名的这种用法,我们这道题是第一次碰到,更加详细的描述,能够在官方文档中的索引签名里面找一下。
TypeScript: Documentation - Indexed Access Types (typescriptlang.org)
总结
今天我们做完了中等的第五题,题目的做法很多,本文主要列出了两种,剩余的可以自己去进行研究,最简单的做法应该就是 TS 提供给我们的索引签名去获取,这种方式简单又能够快速的获取数组的属性的类型的联合类型。