前言
在学习typescript的过程当中,有一个github库对其类型的学习特别有帮助,是一个有点类似于leetcode的刷题项目,能够在里面刷各种关于typescript类型的题目,本片文章带大家做其中简单难度的第六道题 43-easy-exclude
43-easy-exclude
我们首先还是先通过题目的README来看一下题目的要求
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5PTtPsLN-1655351348660)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8d274a3b9e5b43ebb999c6c72e789d0f~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image?)]
type cases = [
Expect<Equal<MyExclude<'a' | 'b' | 'c', 'a'>, Exclude<'a' | 'b' | 'c', 'a'>>>,
Expect<Equal<MyExclude<'a' | 'b' | 'c', 'a' | 'b'>, Exclude<'a' | 'b' | 'c', 'a' | 'b'>>>,
Expect<Equal<MyExclude<string | number | (() => void), Function>, Exclude<string | number | (() => void), Function>>>,
]
结合题目给的README和测试case,我们就能够得出,题目是需要我们实现一个函数,功能和内置的 Exclude 相同,接收一个联合类型,从中剔除掉传入的第二个类型成员,返回一个新的类型,下面我们可以简单地看一下 Exclude 的作用。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gDIaMU67-1655351348660)(https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ac7ffe8cc49b41b3a63bad43eee10942~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image?)]
接下来我们就开始做题
利用js进行对比学习
首先我们还是先用js来模拟题目的要求。
我们用数组来进行模拟,新建一个 JSMyExclude 函数,这个函数传入两个数组,我们需要从第一个数组中剔除掉第二个数组的内容,并且返回剔除后的新数组。
// js
function JSMyExclude(T, U) {
let newArr = [];
T.forEach((e) => {
if (!U.includes(e)) {
newArr.push(e);
}
});
return newArr;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LjckuVYX-1655351348661)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/104d286d466f4ee7bc70a3c7dde6984a~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image?)]
实现 MyExclude
接着我们就按照js的逻辑来实现ts的代码
首先我们需要去循环 T 的每一项并且和 U 中的每一项做一个对比,相同的话就会被剔除,不相同就会返回,那么在ts中我们要怎么去循环对比两个联合类型呢。
在ts中我们可以使用 extends 来对比两个类型的属性。对于extends的一般使用来说:
type Equal<X, Y> = X extends Y ? true : false;
type Num = Equal<1, 1>; // true
type Str = Equal<'a', 'a'>; // true
type Boo = Equal<true, false>; // false
我们可以通过它约束的能力配合三元表达式来做一个简单的值对比,当 X 的类型 都存在于 Y 中的时候,三元表达式就会返回 true,否则返回 false。
并且在映射类型当中,当我们用一个泛型去extends另一个泛型的时候,会将每一个位置上的值都进行比对,并且返回一个联合类型。我们来举一个小例子:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ouwNmxee-1655351348661)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6a806b8b7f584dc89edc676cf9b9bb30~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image?)]
我们会发现当T1和T2相等的时候,返回的值就全是 true 的值,但是当两个值不相等的时候,
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QuUqz0zT-1655351348661)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/179a1caf13aa4bf9a3694918651cc65e~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image?)]
返回的却不是只有 false 的值,而是两个的联合类型,这样我们就能够知道,我们应该怎么去写这个 MyExclude 工具方法。
根据js中的逻辑,当两个值不相等的时候,返回,也就是 T。当两个值相等的时候,不做返回,也就是 never。
type MyExclude<T, U> = T extends U ? never : T;
可以看到这样之后,测试代码已经不会报错了,并且我们自己试用一下 MyExclude 也能够返回正确的结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vyi7qmCN-1655351348661)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9902461d4f194a46935b168199c59b4c~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image?)]
知识点
关于上述提到了部分的知识点:
- extends
- 三元表达式
今天提到的新知识点就是 extends 以及 三元表达式 具体的介绍大家可以看一下文档,这里放上官方文档中关于 条件类型 的文档。
TypeScript: Documentation - Conditional Types (typescriptlang.org)
总结
今天我们认识了 typescript 中的条件类型,作用和使用方法都和 JS 中的三元表达式特别相似,进行一定的对比学习会对我们对它的理解更加的深刻。