title | date | hideComments |
---|---|---|
第九题:Exclude |
2020/05/29 |
false |
实现内置的 Exclude <T, U>
类型,但不能直接使用它本身。
从联合类型 T 中排除 U 的类型成员,来构造一个新的类型。
例如:
type Result = MyExclude<"a" | "b" | "c", "a">; // 'b' | 'c'
type T0 = Exclude<"a" | "b" | "c", "a">; // expected "b" | "c"
type T1 = Exclude<"a" | "b" | "c", "a" | "b">; // expected "c"
::: info 提示 在这个挑战中,你需要修改下方的代码使得测试通过(使其没有类型错误)。并且记得将答案分享奥。 :::
在 ts 中,我们能够使用 Exclude<T,U>
这个工具,帮助我们把 T
类型当中属于 U
类型的部分去除后得到一个新的类型,ts
已经自己提供了,使用方式如下:
type myType = Exclude<"a" | "b" | "c", "a">;
得到的 myType
为 'a'|'b'
,明白 Exclude 的作用以后就可以自己手动实现一个了
首先我们使用 js 来实现,假设 Exclude 为一个函数,类型在这里就当作参数传入函数,返回值作为得到的类型,代码如下所示:
/**
* T: ['a', 'b', 'c']
* U: ['a']
*/
function MyExclude(T: any[], U: any[]) {
const result = [];
for (let i = 0; i < T.length; i++) {
const temp = T[i];
if (!U.includes(temp)) {
result.push(temp);
}
}
return result;
}
const T = ["a", "b", "c"];
const U = ["a"];
MyExclude(T, U); // ['b', 'c']
有上述的函数代码可以知道,在获得最终类型的时候,必定会经过循环,在 ts 中使用 extends
关键字可以实现,ts 的代码实现如下 :
type MyExclude<T, U> = T extends U ? never : T;
这里重要的细节是 TypeScript 中的条件类型 是可分配的。
所以当你在写 T extends U 且 T 是联合类型时,实际上发生的是 TypeScript 遍历联合类 型 T 并将条件应用到每个元素上。
因此,这个解答是非常直接的。我们检查 T 如果可以分配给 U 则跳过:
type MyExclude<T, U> = T extends U ? never : T;