type-challengs/pick - easy

165 阅读2分钟

实现 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中依次匹配属性名所属的类型。
  1. 泛型约束: 包含和被包含的关系 -> extends关键字
  2. 依次遍历,让我想到映射类型 -> [key in K],其中K必须是一个联合类型。
  3. 从T中取出K中属性对应的类型 -> 这个让我想到了索引访问类型。T['key']
  • 尝试解题:
  1. 因为从第二点可以看出,K必须是一个联合类型,而这个联合类型,必须被T所包含。所以有K extends keyof T,keyof T取出了T中所有的属性名并返回一个联合类型

    type Pick<T,K extends keyof T>

  2. 此时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;
	};
  1. 现在我们还缺少这些key的类型,要查找映射类型在T中对应的类型。要注意的是,文档指出索引名本身是一个类型,而不是一个值。于是尝试T[key]。

    type Pick<T, K extends keyof T> = { [key in K] : T[key] }