# 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>]
: [];
# 知识点
- 判断类型相等的逻辑,可以参考 Equals。
- 元组遍历套路