你用过 TypeScript 内置的 Pick 工具类型么?你想知道它内部是如何实现的么?本期阿宝哥将带你一起手写一个 MyPick 工具类型。看完本文之后,你就能了解该工具类型涉及的相关知识点。你准备好了么?现在我们马上进入正题。
这是一个 Pick 函数,它的作用是挑选 keys 属性数组中每个 key 对应的值,组成一个新的对象。
function Pick(obj, keys) {
const ret = {};
for (const key of keys) {
ret[key] = obj[key];
}
return ret;
}
const user = {
id: 666,
name: "阿宝哥",
address: "厦门",
};
const PickedUser = MyPick(user, ["id", "name"]);
在 JavaScript 中我们操作的是对象,而在 TypeScript 中我们操作的是类型。同样,在 TypeScript 中我们也可以把 User 类型转换成只包含 id 和 name 属性的 PickedUser 类型。
type User = {
id: number;
name: string;
address: string;
};
type PickedUser = {
id: number;
name: string;
};
要实现上述的功能,我们需要使用 TypeScript 提供的映射类型。它是一种泛型类型,可用于把原有的对象类型映射成新的对象类型。
映射类型的语法如下:
{ [ P in K ] : T }
其中 P in K 类似于 JavaScript 中的 for...in 语句,用于遍历 K 类型中的所有类型,而 T 类型变量用于表示 TS 中的任意类型。了解完这些知识之后,我们来定义一个 MyPick 工具类型。
type MyPick<T, K extends keyof T> = {
[P in K]: T[P];
};
在以上代码中,T、K 被称为类型参数,与 Pick 函数中参数的作用类似。keyof 操作符用于获取某种类型中的所有键,其返回类型是联合类型。如果 keyof 操作的是对象类型,其功能与 Object.keys 方法类似。
而 K extends keyof T 是泛型约束,用于约束类型参数 K 对应的实际类型为对象类型所有键组成的联合类型的子类型。T[P] 用于获取 T 类型中 P 属性对应的类型,其中类型变量 P 的值会在遍历的过程中不断改变。
下面我们来验证一下 MyPick 工具类型,是否实现对应的功能。在实际工作中,若遇到对应的场景,我们可以直接使用 TypeScript 提供的 Pick 工具类型。
type PickedUser = MyPick<User, "id" | "name">;
// type PickedUser = {
// id: number;
// name: string;
// }
在 TypeScript 中映射类型非常重要,如果你想深入学习映射类型,可以观看 “用了 TS 映射类型,同事直呼内行!