在开发的时候经常会遇到有一些类型定义需要重复定义,但这样维护起来很麻烦,比如我要创建一个文章,这个文章的属性都是必须的,但是当我们没有传其中的参数时会有默认值,因此这些参数可能就不是必传的,那这样我们就需要定义相同的类型属性两次,实现需求,但是这样维护起来比较麻烦
本文我们定义一个

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详细说明请查看 - &:表示交叉类型,关于交叉类型详细说明请查看