前言
简单题:实现Pick
TS Playground:github.com/type-challe…
正文
题目
4 - Pick
-------
by Anthony Fu (@antfu) #easy #union #built-in
### Question
Implement the built-in `Pick<T, K>` generic without using it.
Constructs a type by picking the set of properties `K` from `T`
For example:
interface Todo {
title: string
description: string
completed: boolean
}
type TodoPreview = MyPick<Todo, 'title' | 'completed'>
const todo: TodoPreview = {
title: 'Clean room',
completed: false,
}
> View on GitHub: <https://tsch.js.org/4>
/* _____________ Your Code Here _____________ */
type MyPick<T, K> = any
/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'
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
}
答案
type MyPick<T, K extends keyof T> = {
[key in K]: T[key]
};
总结
keyof:取interface的键保存为联合类型
interface user {
name: string,
age: number
}
type keyofUser = keyof user;
// keyofUser = 'name' | 'age'
in:取联合类型的值,主要用于数组和对象的构建
type name = 'firstname' | 'lastname';
type TName = {
[key in name]: string
};
// TName = { firstname: string, lastname: string };
实际运用举例:
function getVal(o: object, k: string) {
return o[k];
}
const user = { name: '张三', age: 18 };
const nameVal = getVal(user, 'name'); // 张三
以上写法的缺点:
- 无法确定返回值类型
- 无法对 key 进行约束
function getVal<T extends object, K extends keyof T>(o: T, k: K): T[K] {
return o[k];
}
const user = { name: '张三', age: 18 };
const nameVal = getVal(user, 'name'); // 张三
此时,如果第二个参数 k 不是 user 的 key 值(name/age)就会报错