实现 Pick
题目:传送门
从类型
T
中选择出包含在集合 K
中的属性,构造成一个新的类型。(即实现 TS 内置的 Pick<T, K>
)例如:
interface Todo {
title: string
description: string
completed: boolean
}
type TodoPreview = MyPick<Todo, 'title' | 'completed'>
思路与要点:
TS 中,可以使用
extends
运算符来判断一个属性是否在集合类型 Union Type
中:例如:
type r1 = 'title' extends 'title' | 'completed' ? true : false // type r1 = true
利用这个特性,我们可以实现这样一种类型:
type MyPick<T, P> = {
[K in keyof T]: K extends P ? never : T[K]
}
但这样我们会发现,不属于类型
P
的属性会变成 never
:type r2 = MyPick<Todo, 'title' | 'completed'>
/**
* type r2 = {
* title: string
* description: never
* completed: boolean
* }
*/
由此,我们需要排除掉
K
中不属于 P
的类型,可以实现一个工具类型 Exclude
:type Exclude<T, U> = T extends U ? never : T
然后改造
MyPick
的实现形式:type MyPick<T, P extends keyof T /* 约束 P 的类型,只允许从 T 的属性中取值 */> = {
[K in Exclude<keyof T, P>]: T[K]
}
来看下最后的结果:
type r3 = MyPick<Todo, 'title' | 'completed'>
/**
* type r3 = {
* title: string
* completed: boolean
* }
*/
符合要求🥳。
实现 Readonly
题目:传送门
将类型
T
中所有的属性,标记为 readonly
。(即实现 TS 内置的 Readonly<T>
)例如:
interface Todo {
title: string
description: string
}
type TodoReadonly = MyReadonly<Todo>
/**
* type TodoReadonly = {
* title: readonly string
* description: readonly string
* }
*/
思路与要点:
这道题考察点比较简单,我们只需要遍历类型
T
中的所有属性,然后给它们加上 readonly
修饰就可以了:type MyReadonly<T> = {
[K in keyof T]: readonly T[K]
}
来看下结果:
type r4 = MyReadonly<Todo>
/**
* type r4 = {
* title: readonly string
* description: readonly string
* }
*/
也是符合要求的🥳。