测试 case
type cases = [
Expect<Equal<Expected1, MyPick<Todo, 'title'>>>,
Expect<Equal<Expected2, MyPick<Todo, 'title' | 'completed'>>>,
// @ts-expect-error
MyPick<Todo, 'title' | 'completed' | 'invalid'>,
]
interface Todo {
title: string
description: string
completed: boolean
}
interface Expected1 {
title: string
}
interface Expected2 {
title: string
completed: boolean
}
- template.ts
type MyPick<T, K> = any
首先我们可以把我们的 MyPick 先用js实现,然后把 js 转成 ts
const myPick = (todo, keys) => {
const obj = {}
keys.forEach(key => {
if (key in todo) {
obj[key] = todo[key]
}
})
return obj
}
步骤:
// 1. 返回一个对象
// 2. 遍历keys
// 3. todo[key] 取值
// 4. 看看 key 在不在 todo 里面
将上面的步骤转成 ts
// 1. 返回一个对象直接写一个对象
type MyPic<T, K> = {}
// 2. 遍历keys
// 这里的 K 是 'title' | 'completed' 也就是联合类型,联合类型的遍历用 in
// 把 'title' 或者 'completed' 给一个变量我们用P表示
[P in K]
// 3. todo[key] 取值
[P in K]: T[P]
// 4. 看看 key 在不在 todo 里面
K extends keyof T
// keyof 可以获取 T 的所有 key,比如
//interface Todo {
// title: string
// description: string
// completed: boolean
//}
// keyof Todo // 'title' | 'description' | 'completed'
// extends 关键字对 K 进行约束,也就是 K 必须是 'title' | 'description' | 'completed'
最终实现代码
type MyPick<T, K extends keyof T> = {
[P in K]: T[P]
}
网友评论