Skip to content

Latest commit

 

History

History
93 lines (66 loc) · 3.11 KB

1.9.exclude.md

File metadata and controls

93 lines (66 loc) · 3.11 KB
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"

点击github查看:

挑战

::: 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;

参考