在开发的时候经常会遇到有一些类型定义需要重复定义,但这样维护起来很麻烦,比如我要创建一个文章,这个文章的属性都是必须的,但是当我们没有传其中的参数时会有默认值,因此这些参数可能就不是必传的,那这样我们就需要定义相同的类型属性两次,实现需求,但是这样维护起来比较麻烦
本文我们定义一个
interface Article { title: string; content: string; author: string; date: Date; readCount: number; } type Optional<T, K> = {}; type createArticleOptions = Optional<Article, "">; /** * 经过Optional处理后我们得到下面的接口 * interface createArticleOptions { title: string; content: string; author?: string; date?: Date; readCount?: number; } */
实现
interface Article { title: string; content: string; author: string; date: Date; readCount: number; } type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>; type createArticleOptions = Optional<Article, "author" | "date" | "readCount">; function createArticle(options: createArticleOptions) {}
上面的代码就实现了我们期望的结果,如下图
简单解析一下
- <T, K extends keyof T>:
T 是一个类型参数,表示要操作的类型。K 是另一个类型参数,并用keyof T 约束它,表示K 必须是类型T 的键(属性名)的子集 - Omit<T, K>:
T 表示原始类型,K 表示要从原始类型T 中剔除的属性 - Pick<T, K>:
T 表示原始类型,K 表示需要从原始类型T 中选取的属性名 - Partial:是ts官方提供的一个工具方法,生成一个新类型,该类型与T拥有相同的属性,但是所有属性皆为
可选的 ,关于Partial详细说明请查看 - &:表示交叉类型,关于交叉类型详细说明请查看