实现 TS 内置的 Pick<T, K>
从类型 T 中选择出属性 K,构造成一个新的类型。
interface Todo {
title: string
description: string
completed: boolean
}
type TodoPreview = MyPick<Todo, 'title' | 'completed'>
const todo: TodoPreview = {
title: 'Clean room',
completed: false,
}
- 解题思路:题中的K是一个联合类型。这个联合类型中的每一个属性名都要被包含在T的属性名中。将这些属性名取出,然后在T中依次匹配属性名所属的类型。
- 泛型约束: 包含和被包含的关系 -> extends关键字
- 依次遍历,让我想到映射类型 -> [key in K],其中K必须是一个联合类型。
- 从T中取出K中属性对应的类型 -> 这个让我想到了索引访问类型。T['key']
- 尝试解题:
-
因为从第二点可以看出,
K必须是一个联合类型,而这个联合类型,必须被T所包含。所以有K extends keyof T,keyof T取出了T中所有的属性名并返回一个联合类型。type Pick<T,K extends keyof T>
-
此时
T是泛型,K是一个被约束在T属性名组成的联合类型中的联合类型。 紧接着,是从K中依次拿到所有字符串,并且逐一在T中匹配。这个思路很像循环,根据这个思路从文档中能找到符合条件的映射类型type Pick<T,K extends keyof T> = [key in K]
tips: 映射类型,就是使用了
PropertyKeys联合类型的泛型,其中PropertyKeys多是通过keyof创建,然后循环遍历键名创建一个类型 — 就是说in关键字后面的类型是一个联合类型,通常由keyof创建。而前面的key其实是被这个联合类型循环的某一个属性(propertyKey),而:的左侧就是映射类型[key in K],而:右侧是一个类型比如:string以下是一个官方文档的例子,这可能会有助于你的理解。
type OptionsFlags<Type> = {
[Property in keyof Type]: boolean;
};
-
现在我们还缺少这些key的类型,要
查找映射类型在T中对应的类型。要注意的是,文档指出索引名本身是一个类型,而不是一个值。于是尝试T[key]。type Pick<T, K extends keyof T> = { [key in K] : T[key] }