持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第25天,点击查看活动详情
1. 引言
接着上一节中,接下来我们继续Ts中等篇的题型练习
https://github.com/type-challenges/type-challenges/blob/main/README.zh-CN.md 提供的TypeScript 类型体操姿势合集题型,目的是为了让大家更好的了解TS的类型系统,编写自己的类型工具,或者单纯的享受挑战的乐趣!
2. 题型
- 实现一个通用Pop,它接受一个数组T并返回一个没有最后一个元素的数组。
type arr1 = ['a', 'b', 'c', 'd']
type arr2 = [3, 2, 1]
type re1 = Pop<arr1> // expected to be ['a', 'b', 'c']
type re2 = Pop<arr2> // expected to be [3, 2]
思路: 使用[...]配合infer 关键字 解答:
type Pop<T extends any[]> = T extends [...infer R,infer Z] ? R : never
type Demo = Pop<[3, 2, 1]> // type Demo = [3, 2]
type Demo2 = Pop<['a', 'b', 'c', 'd']> // type Demo2 = ["a", "b", "c"]
- 键入函数PromiseAll,它接受PromiseLike对象数组,返回值应为Promise,其中T是解析的结果数组。
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise<string>((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
});
// expected to be `Promise<[number, 42, string]>`
const p = Promise.all([promise1, promise2, promise3] as const)
思路: 首先我们要理解下,当一个TypeScript 获取Promise.resolve 的返回值结果类型是什么
const ValPromise = Promise.resolve(3)
type TypePromise = typeof ValPromise // type TypePromise = Promise<number>
由上述可知:返回的是一个Promise 对象类型,接着我们来了解下as const 是什么 as const: 类型断言的一种,是一种类型缩窄的方式,并设置类型为只读属性
const TursFun = [1, 2, 3] as const
const NomalFun = [1, 2, 3]
type TypeTursFu = typeof TursFun // type TypeTursFu = readonly [1, 2, 3]
type Nomal = typeof NomalFun // type Nomal = number[]
type Whether = TypeTursFu extends Nomal ? true : false // type Whether = false
type Whether2 = [1,2] extends [1,2,3] ? true : false // type Whether2 = false
所以此题的思路就是:先约束形参为数组,并设置只读书写,确认PromiseAll 返回的Promise,T为数组, 使用映射操作符轮询每个键值判断是否为Promise 对象,是的话通过·infer R 关键字抛出入参,否则返回对象本身。 解答:
declare function PromiseAll<T extends any[]>(values: readonly [...T]): Promise<{[K in keyof T]: T[K] extends Promise<infer R> ? R : T[K]}>
const promiseAllTest1 = PromiseAll([1, 2, 3] as const)
const promiseAllTest2 = PromiseAll([1, 2, Promise.resolve(3)] as const)
const promiseAllTest3 = PromiseAll([1, 2, Promise.resolve(3)])
type Demo = typeof promiseAllTest1 // type Demo = Promise<[1, 2, 3]>
type Demo2 = typeof promiseAllTest2 // type Demo2 = Promise<[1, 2, number]>
type Demo3 = typeof promiseAllTest3 // type Demo3 = Promise<[number, number, number]>
- 实现一个通用Unshift,向数组的开头添加一个或更多元素,并返回新的长度。
思路: 使用[...]配合infer 关键字
解答:
type arr1 = ['a', 'b', 'c', 'd']
type arr2 = [3, 2, 1]
type Unshift<T extends any[],U,Z> = [U,Z,...T]
type Demo = Unshift<arr1,'m','n'> // type Demo = ["m", "n", "a", "b", "c", "d"]
type Demo1 = Unshift<arr2,'zzz',5> // type Demo1 = ["zzz", 5, 3, 2, 1]