# 399-元组过滤器

# 题目描述

Implement a type FilterOut<T, F> that filters out items of the given type F from the tuple T.

For example,

type Filtered = FilterOut<[1, 2, null, 3], null>; // [1, 2, 3]

# 分析

这个题目本质就是遍历元组,判断每个元素是否在要过滤的名单中即可。

其实之前做过一个非常类似的题目:5117-去除数组指定元素

只不过二者中第二个参数格式不同,5117 是元组,而本题,从用例来看是,联合类型。用例如下:

type cases = [
  Expect<Equal<FilterOut<[], never>, []>>,
  Expect<Equal<FilterOut<[never], never>, []>>,
  Expect<Equal<FilterOut<['a', never], never>, ['a']>>,
  Expect<Equal<FilterOut<[1, never, 'a'], never>, [1, 'a']>>,
  Expect<
    Equal<
      FilterOut<
        [never, 1, 'a', undefined, false, null],
        never | null | undefined
      >,
      [1, 'a', false]
    >
  >,
  Expect<
    Equal<
      FilterOut<[number | null | undefined, never], never | null | undefined>,
      [number | null | undefined]
    >
  >,
];

那么思路其实就有了,把联合转为元组(并不简单,可以在后续的困难题中找到 730-联合转元组),复用 5117-去除数组指定元素 的答案即可。

这里来看看不转换的做法。

要判断一个联合类型 U 中是否包含某个类型 A 的,可以通过 [A] extends [U] ? true : false,但是这种判断手段,存在一些特殊的 case,为什么加 [],在 Equals 中有详细说明。

但是也存在一些场景判断不出来,就是,字面量的情况:[1] extends [number | '1'] ? true : false,会返回 true。

好在这题并没有这种刁钻的 case,所以遍历一次元组,通过 [A] extends [U] ? true : false 来进行判断是否要过滤元素即可实现。

# 题解

type FilterOut<T extends any[], F> = T extends [infer First, ...infer R]
  ? [First] extends [F]
    ? FilterOut<R, F>
    : [First, ...FilterOut<R, F>]
  : [];

# 知识点

  1. 判断类型相等的逻辑,可以参考 Equals
  2. 元组遍历套路
Last Updated: 2023/5/16 06:00:28