背景
在使用TS开发项目的时候,有一些比较实际的需求,比如:
我现在有一个创建文档的方法,如下:
interface Document {
title:string;
content:string;
status:number;
author:string;
date:string;
readCount:number;
}
interface DocumentOptions{
title:string;
content:string;
status?:number;
author?:string;
date?:string;
readCount?:number;
}
function createDocument(options:DocumentOptions): Article {
let article = {} as Document;
article.title = options.title;
article.content = options.content;
article.status = options.status || 0;
article.author = options.author || 'admin';
article.date = options.date || new Date().toISOString();
article.readCount = options.readCount || 0;
return article;
}
可以看到Document和DocumentOptions属性内容相同,只有一些必填非必填的区别,我在想有没有一种方法让我可以在Document 的基础上把一些字段转为非必填呢?像下面这样:
interface Document {
title:string;
content:string;
status:number;
author:string;
date:string;
readCount:number;
}
type DocumentOption = CreateDocumentOption<Document, 'status'|'author'|'date'|'readCount'>;
// DocumentOption得到的结果如下
type DocumentOption = {
title:string;
content:string;
status?:number;
author?:string;
date?:string;
readCount?:number;
}
遗憾的是TS并没有给我们提供这样的方法,我们只能自己写一个方法实现这个功能了,实现结果如下:
type CreateDocumentOptions<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
// 使用
type DocumentOption = CreateDocumentOption<Document, 'status'|'author'|'date'|'readCount'>;
关键词解释
&
&符号表示交叉类型(Intersection Types)。交叉类型允许将多个类型合并为一个类型,该类型将具有所有类型的属性和方法。例如:
interface A {
a: string;
}
interface B {
b: string;
}
type C = A & B;
// C的结果
type C = {
a: string;
b: string;
}
Omit
- Omit 是一个内置的类型工具,用于从对象类型中排除指定的属性。 例如:
interface D {
d: string;
e: string;
f: string;
}
type E = Omit<D, 'd' | 'e'>;
// E的结果
type E = {
f: string;
}
Pick
- Pick 是一个内置的类型工具,用于从对象类型中选择指定的属性创建新的类型。例如:
interface F {
f: string;
g: string;
h: string;
}
type G = Pick<F, 'f' | 'g'>;
// G的结果
type G = {
f: string;
g: string;
}
Partial
- Partial 是一个内置的类型工具,用于将对象类型中的所有属性变为可选属性。例如:
interface H {
h: string;
i: string;
j: string;
}
type I = Partial<H>;
// I的结果
type I = {
h?: string;
i?: string;
j?: string;
}
通过综合使用&、Omit、Pick、Partial就可以实现将类型中的部分属性修改为可选属性了。