omit英文的意思对应的就是省略的意思。
Omit是什么
Omit
是TypeScript3.5新增的一个辅助类型,它的作用主要是:以一个类型为基础支持剔除某些属性,然后返回一个新类型。
type Person = {
name: string;
age: string;
location: string;
};
type PersonWithoutLocation = Omit<Person, 'location'>;
// PersonWithoutLocation equal to QuantumPerson
type QuantumPerson = {
name: string;
age: string;
};
Omit背后定义
那接下来我们看看Omit
内部是如何实现的。
// lib.es5.d.ts
/**
* Construct a type with the properties of T except for those in type K.
*/
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
接下来就是理解下这段代码。
keyof运算符
keyof
诞生于TypeScript2.1版本,它的作用是:帮助我们获取某种类型的所有键,返回的是一个联合类型。s 我们可以看一个很常见的示例:
function getProperty<T, K extends keyof T>(obj: T, key: K) {
return obj[key]; // Inferred type is T[K]
}
function setProperty<T, K extends keyof T>(obj: T, key: K, value: T[K]) {
obj[key] = value;
}
Exclude
用法:Exclude<Type, ExcludedUnion>
。简单理解Exclude
就是数学集合中找出Type的“差集”,就是将类型A与B对比,返回A中独有的类型。
看一个示例:
那么大家肯定也会好奇Exclude
背后的定义是怎么样的。
/**
* Exclude from T those types that are assignable to U
*/
type Exclude<T, U> = T extends U ? never : T;
Extends
T extends U ? never : T
这里的extends
可与class的extends
不是一回事,这里指的是条件类型。
这里不做过多的扩展,重点通过一个概念分布式条件类型来理解上面Exclude
的写法。
type A = 'a' | 'b' | 'c';
type B = 'a';
type C = Exclude<A, B>; // 'b' | 'c';
// A extends B ? never : A 等价于 ('a' | 'b' | 'c') extends B ? never : ('a' | 'b' | 'c') 等价于如下
type D = ('a' extends B ? never : 'a') | ('b' extends B ? never : 'b') | ('c' extends B ? never : 'c'); // 'b' | 'c';
Pick
Pick<Type, Keys>
,顾名思义:拣选属性,将 Type
的部分类型 Keys
挑出来,返回这部分类型。
其背后的定义就比较好理解了:
// 通过keyof操作符+索引类型T[P]实现
/**
* From T, pick a set of properties whose keys are in the union K
*/
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
怎么推导Omit
通过上面前置知识,相信很好的理解了type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
。下面我们一步步推导上述“公式”加深知识的理解。
type Person = {
name: string;
age: string;
location: string;
};
type PersonWithoutLocation = Omit<Person, 'location'>;
// 推导
type PersonWithoutLocation = Pick<Person, Exclude<'name' | 'age' | 'location', 'location'>>;
// 推导
type PersonWithoutLocation = Pick<Person, (('name' extends 'location' ? never : 'name') | ('age' extends 'location' ? never : 'age') | ('location' extends 'location' ? never : 'location'))>;
// 推导
type PersonWithoutLocation = Pick<Person, ('name' | 'age' | never)>;
// 推导
type PersonWithoutLocation = Pick<Person, ('name' | 'age')>;
// 推导
type PersonWithoutLocation = {
[p in 'name' | 'age']: Person[p]
};
// 推导
type PersonWithoutLocation = {
name: string;
age: string;
}
正文完
发表至: NuxtJS
2023-12-22