Skip to content

在TypeScript数组中如何优雅的过滤掉null

约 818 字大约 3 分钟

TypeScript

2025-01-06

编码过程中,经常需要过滤掉可选数组中的某个类型的值,如过滤null。一般使用数组的filter即可完成,如下:

const arr: (string | null)[] = []
const fArr = arr.filter((item) => item !== null)
// fArr type is: (string | null)[]

如上使用filter,确实实现了过滤掉null的需求,但是TypeScript对结果的类型还是推断为(string | null)[],并不是我们期望的string[]。 如果希望TypeScript正确识别出过滤掉null后的类型,我们应该如何做呢?可以使用如下方法:

  • 使用as指定过滤后的结果的类型
  • 使用is指定返回项的类型
  • 使用is+Exclude来收窄类型。

使用as指定结果类型

通过as手动指定过滤结果的类型,如下:

const arr: (string | null)[] = []
const fArr = arr.filter((item) => item !== null) as string[]
// fArr type is: string[]

这是最简单的实现,通过指定结果的类型来实现。 这个方案需要注意的是,我们要能拿到类型,如果使用三方库,我们可能获取不到类型申明,就比较麻烦。还有就是不要把类型写错了,影响到后面的推断。

使用is指定返回项的类型

同使用使用as指定结果类型,差不多。这里我们只需要指定每次处理后的返回的结果的类型,这样TypeScript就能推断出过滤后的结果类型。

const arr: (string | null)[] = []
const fArr = arr.filter((item): item is string => item !== null)
// fArr type is: string[]

这个方案也是可行的,但是还是存在同样的问题,当我们无法获取到类型时,是无法使用该方案的。这就衍生出了下面的一种处理方式。

使用is+Exclude来收窄类型

如下,可以使用is+Exclude的方式来收窄类型。

const arr: (string | null)[] = []
const sArr = arr.filter((item): item is Exclude<typeof item, null> => item !== null)
// fArr type is: string[]

这里使用了Exclude来排除掉null类型,然后再使用is来指定返回值的类型,这样TypeScript就能正确推断出过滤后的结果类型。 这个方案就没有获取具体类型得要求,我们通过typeof来处理的,不需要知道具体类型。

提示 这里还有个小技巧,如果想顺便处理掉空字符,可以改一下判断条件

const arr: (string | null)[] = []
const sArr = arr.filter((item): item is Exclude<typeof item, null> => !!item)
// fArr type is: string[]

总结

上面介绍了如何在TypeScript数组中过滤掉null,并正确推断出过滤后的结果类型。 如果比较简单,asis都是不错的选择。 如果不能获取到具体的类型,我们可以使用is+Exclude来收窄类型。

注意 虽然这里举例是过滤数组中的null项。但是思路是通用的,也可以在过滤其他类型使用类似的方式。

参考

stackoverflow TypeScript filter out nulls from an array