小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
序言:
这是搞定 TS 第十篇,如果没有基础的小伙伴想要从零搞定 TS ,请从第一篇开始juejin.cn/post/701033…
第一题
实现一个 Merge 工具类型,用于把两个类型合并成一个新的类型。第二种类型(SecondType)的 Keys 将会覆盖第一种类型(FirstType)的 Keys。具体的使用示例如下所示:
type Foo = {
a: number;
b: string;
};
type Bar = {
b: number;
};
type Merge<FirstType, SecondType> = // 你的实现代码
const ab: Merge<Foo, Bar> = { a: 1, b: 2 };
考察知识
解法一
- 先将第一种类型中和第二种类型中重复的属性删除,再用结果交叉第二种属性即可达到目的。
type Foo = {
a: number;
b: string;
};
type Bar = {
b: number;
};
type Merge<FirstType, SecondType> = Omit<FirstType, keyof SecondType> & SecondType
const ab: Merge<Foo, Bar> = { a: 1, b: 2 };
解法二
- 将两种类型交叉,得到所有属性
- 遍历所有属性进行判读,首先判断是否属于属性二,属于则使用属性二,否则使用属性一对应的属性。
type Foo = {
a: number;
b: string;
};
type Bar = {
b: number;
};
type Merge<FirstType, SecondType> = {
[ P in keyof FirstType & SecondType]
: P extends keyof SecondType? SecondType[P]
: FirstType[P]
}
const ab: Merge<Foo, Bar> = { a: 1, b: 2 };
第二题
实现一个 RequireAtLeastOne 工具类型,它将创建至少含有一个给定 Keys 的类型,其余的 Keys 保持原样。具体的使用示例如下所示:
type Responder = {
text?: () => string;
json?: () => string;
secure?: boolean;
};
type RequireAtLeastOne<
ObjectType,
KeysType extends keyof ObjectType = keyof ObjectType,
> = // 你的实现代码
// 表示当前类型至少包含 'text' 或 'json' 键
const responder: RequireAtLeastOne<Responder, 'text' | 'json'> = {
json: () => '{"message": "ok"}',
secure: true
};
考察知识
- Pick<T,V> (从 T 类型 挑选 V 类型)
- Required
- 交叉类型的应用
type Responder = {
text?: () => string;
json?: () => string;
secure?: boolean;
};
type RequireAtLeastOne<
ObjectType,
KeysType extends keyof ObjectType = keyof ObjectType,
> = KeysType extends keyof ObjectType ? ObjectType & Required< Pick<ObjectType,KeysType>>:never
// 表示当前类型至少包含 'text' 或 'json' 键
const responder: RequireAtLeastOne<Responder, 'text' | 'json'> = {
json: () => '{"message": "ok"}',
secure: true
};//成立
const responder1: RequireAtLeastOne<Responder, 'text' | 'json'> = {
text: () => '{"message": "ok"}',
secure: true
};//成立
const responder2: RequireAtLeastOne<Responder, 'text' | 'json'> = {
secure: true
};//报错
小结: 该题的解题思路就是将传入的联合类型,从目标对象中取出转换为必选,其他的不变。有一点让人疑惑的地方就是,全部转换为必选类型,为啥最后有一个就行,那是因为联合类型会分布运算。