一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情。
中等
最后一个元素
type Last<T extends readonly any[]> = T extends [...infer R, infer L] ? L : T;
- 因为元组支持
rest元素,所以通过extends搭配infer就可以获取到最后一个元素的类型了
在解答区看到一个👍比较多的答案,我的答案兼职low爆了:
type Last<T extends any[]> = [any, ...T][T["length"]];
- 首先通过
[any, ...T]组成了一个新的元组类型 - 使用索引访问类型可以获取对应的属性,只要是数组上的属性,都可以使用:
而TS是可以推断出元组类型的长度的,所以T["length"]是可以获得具体数值的,从而获取最后一个元素的类型。
例子:
type A = Last<[1, 2, 3]>
// 相当于
type A = [any, 1, 2, 3][3]
出堆
type Pop<T extends any[]> = T extends [...infer R, any] ? R : T;
extends是跟infer搭配使用的- 通过
rest元素组成新的元组
额外的:实现Shift、Push、Unshift。
type Shift<T extends any[]> = T extends [any, ...infer R] ? R : T;
type Push<T extends any[], K> = [...T, K];
type Unshift<T extends any[], K> = [K, ...T];
- 道理就跟上面差不多了,利用的都是元组的特性
Promise.all
type TupleType<T extends any[]> = {
[P in keyof T]: T[P] extends Promise<infer R> ? R : T[P]
}
declare function PromiseAll<T extends any[]>(values: readonly [...T]): Promise<TupleType<T>>
[...T]的目的就是使用rest元素创建一个元组类型,看个例子:
type A<T extends any[]> = [...T]
type B = A<[1, 2, 3]>
// 相当于:
type B = [1, 2, 3]
- 而使用
readonly修饰[...T]就变成了只读元组类型 - 最后就是通过
TupleType来遍历元组,把元组中的元素类型按照条件进行处理
Type Lookup
type LookUp<U, T extends string> = U extends { type: T } ? U : never;
例子:
type Animal = Cat | Dog
LookUp<Animal, 'dog'>
因为使用泛型U的时候传入联合类型,所以搭配上extends就变成了分布类型,相当于:
Cat extends { type: T } ? Cat : never | Dog extends { type: T } ? Dog : never
类型结构之间,参数少的兼容参数多的,所以通过{ type: T }这个结构就可以获得想要的结果了。