大家好,我是前端西瓜哥。今天我们来做一道 TypeScript 类型编程题。
我们需要实现一个 RequiredPick 类,从一个对象类型中提取指定的 key 生成新的对象类型,并将它的所有 key 设置为必填。
代码语言:javascript复制type RequiredPick<T, K> = any // 完成这个类型
type Obj = {
a: number;
b?: string;
c: boolean;
}
type ResType = RequiredPick<Obj, 'a' | 'b'>;
// 上面的类型要和下面的类型相等
type ExpectedType = {
a: number;
b: string; // 注意这里没有可选标识 ?
}
如果你想要真正判断两个类型是否相等,而且是靠肉眼确认,这里有一个用于比较的高级类型:
代码语言:javascript复制type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false
Equal 接受两个类型,如果相等返回 true,不相等返回 false。
Pick
我们容易想到 Pick 的实现,Pick 是 TypeScript 内置的一个高级类型。这个类型的实现在我以前的文章《类型体操:探究 TypeScript 内置高级类型》有讲解过。
它的实现如下:
代码语言:javascript复制/**
* From T, pick a set of properties whose keys are in the union K
*/
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
Pick 接受两个类型 T 和 K,K 必须为 T 对象的 key 组成的联合类型的子类型。
{ [P in K]: T[P]; }
是对类型进行 重映射,这里的 P in K
表示遍历 K(K 是遍历类型),然后作为重映射类型的新 key,并且将 T[P]
作为值。
关于 Mapped Types(重映射),更多说明可以看这篇官方文档:
https://www.typescriptlang.org/docs/handbook/2/mapped-types.html
可选 -> 必填
Pick 不能将可选的 key 变成必选的,我们需要在这上面做一些调整。
没错,很简单。。。只需要 :
前边加上 -?
。
实现为:
代码语言:javascript复制type RequiredPick<T, K extends keyof T> = {
[P in K]-?: T[P];
};
除了有 -?
将key 替换为必选,我们还有 -readonly
的写法,将只读 key 转换为普通 key。
然后打个广告,前端大佬神光的 TypeScript 体操教材,如果你想入门的话,这个挺适合,也不贵。
结尾
如果你想练习类型编程,可以尝试做 github 上一个名为 type-challenges 的项目的题目。
我是前端西瓜哥,欢迎关注我,学习更多知识。