小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
尬聊
- Q: 猪猪萌新,根据官方文档,接下去应该是讲Omit了吧
- A: 对,但我就是不讲,你拿我怎么办
- Q: 那为什么要跳着讲啊,这不科学啊
- A: 我自然有自己的想法啦,因为Omit功能用到了我们今天要讲的Exclude哦
- Q: 那为什么你还要在讲Extract?
- A: 那是因为Exclude和Extract长的很像,他们实现上也很接近啦哈哈
正文
一口气讲2个,不知道XDM顶不顶的住,但这2个真的很简单,不信我们接下来看下
官方例子
先来看下官方Exclude的例子,以及说明,该功能主要是排除,我就直接注释里讲解
Constructs a type by excluding from Type all union members that are assignable to ExcludedUnion.
type T0 = Exclude<"a" | "b" | "c", "a">;
// type T0 = "b" | "c", a和b和c,我排除a之后还剩谁,大声告诉我,对,当然就只有b和c啦
type T1 = Exclude<"a" | "b" | "c", "a" | "b">;
// type T1 = "c",a和b和c,我排除a和b之后还剩谁,大声告诉我,对,当然只剩c啦
type T2 = Exclude<string | number | (() => void), Function>;
// type T2 = string | number,string和number还有个方法,我排除方法后还剩谁,当然就只有string和number啦
再来看下官方Extract的例子,以及说明,该功能我理解就是取交集,照样注释里讲解
Constructs a type by extracting from Type all union members that are assignable to Union.
type T0 = Extract<"a" | "b" | "c", "a" | "f">;
// type T0 = "a", abc和af取交集,那不就是a是公共部分嘛
type T1 = Extract<string | number | (() => void), Function>;
// type T1 = () => void,(string,number,方法)和方法取交集,得到了方法,这就是他们的公共交集
所以基于上面的讲解,我们来个小题再来测试下
type Test1 = Exclude<"a" | "b" | "c", "a">;
type Test2 = Extract<"a" | "b" | "c", "a">;
答案公布
- Test1 排除a,那就是
"b" | "c"
- Test2 取交集,那就是
"a"
源码讲解
直接上源码
/**
* Exclude from T those types that are assignable to U
*/
type Exclude<T, U> = T extends U ? never : T;
/**
* Extract from T those types that are assignable to U
*/
type Extract<T, U> = T extends U ? T : never;
看实现,不难发现,其实这俩兄弟,就是倒过来的,以Exclude来举例,T extends U ? never : T
这就是三目, 还记得前面我们type Test1 = Exclude<"a" | "b" | "c", "a">;
排除a,只剩bc嘛,这边带入实现看,就是这样子的逻辑
- a extends a -> 返回never -> 所以a类型被排除了
- b extends a -> 返回T -> 所以b类型保留
- c extends a -> 返回T -> 所以c类型保留 最后就只有bc保留了,XDM可以在捋一下Extract的实现,最后在自己手动实现下,稳稳的就能掌握啦,今天的水文到此结束!