掌握 TypeScript Omit 泛型,一起完成 Type 挑战,巩固 TypeScript 知识。
为了帮助读者更好地巩固 TypeScript 的知识,我从 Github 上的 type-challenges 库中选择了几十个挑战,与您一起完成类型挑战。
挑战
实现内置的 Omit<T, K>
泛型。通过从 T
中挑选所有属性,然后删除 K
来构造一个类型。
例如:
interface Todo {
title: string
description: string
completed: boolean
}
type TodoPreview = MyOmit<Todo, 'description' | 'title'>
const todo: TodoPreview = {
completed: false,
}
解决方案
我们的类型挑战是实现内置的 Omit<Type,Keys>
泛型,所以让我们首先理解 Omit<Type,Keys>
泛型的作用。
Omit<Type,Keys>
通过从 Type
中选择所有属性,然后删除 Keys
(字符串字面量或字符串字面量的并集),构造一个类型。
对于 TypeScript 的 Omit
泛型,它的作用是将现有的对象类型转换为新的对象类型。
为了实现上述类型转换,我们需要遍历除 Keys 以外的所有类型并返回新的对象类型,为此,我们需要使用 TypeScript 提供的映射类型。
映射类型
映射类型的语法如下:
其中 P in K 类似于 JavaScript 中的 for...in
语句,用于遍历类型 K 中的所有类型,而 T 类型变量用于表示 TypeScript 中的任何类型。
在介绍相关知识之后,让我们定义一个 MyOmit
泛型。
type MyOmit<T, K extends keyof any> = {
[P in Exclude<keyof T, K>]: T[P]
}
在上面的代码中, T
和 K
被称为类型参数。 keyof
操作符用于获取一个类型中的所有键,其返回类型是一个联合类型。如果 keyof
操作对象类型,则其功能类似于 Object.keys
方法。
而 K extends keyof any
是一个泛型约束,用于约束类型参数 K
对应的实际类型是联合类型( string | number | symbol
)的子类型, T[P]
用于获取T类型中P属性对应的类型,其中类型变量P的值在遍历过程中会不断变化。
Exclude
泛型是 TypeScript 中的一个内置实用类型,它的角色是通过从 UnionType
中排除所有可赋值给 ExcludedMembers
的联合成员来构造一个类型。
事实上, Exclude
泛型的实现并不复杂,它在内部使用了条件类型。如果您对条件类型还不熟悉,可以阅读以下文章:
像专家一样使用TypeScript条件类型
/**
* Exclude from T those types that are assignable to U.
* typescript/lib/lib.es5.d.ts
*/
type Exclude<T, U> = T extends U ? never : T;
为了更好地理解 Exclude
泛型,让我们来看看它是如何工作的:
完整的代码
最后,让我们看一下完整的代码:
interface Todo {
title: string;
description: string;
completed: boolean;
}
type MyOmit<T, K extends keyof any> = {
[P in Exclude<keyof T, K>]: T[P];
};
type TodoPreview = MyOmit<Todo, "description" | "title">;
const todo: TodoPreview = {
completed: false,
};
这个挑战涉及到的主要知识是 TypeScript 的映射类型,如果你想了解更多关于映射类型的信息,可以阅读以下文章:
像专家一样使用TypeScript映射类型
除了上面的实现,我们还可以使用 Pick
泛型来实现 MyOmit
泛型:
type MyOmit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
欢迎关注公众号:文本魔术,了解更多