扩展RxJS自定义filterNullish运算符以支持数组输入并修正类型
扩展RxJS的filterNullish运算符支持数组输入并完善类型推导
需求说明
现有filterNullish运算符仅能过滤单个值中的null/undefined,现在需要扩展它支持数组输入:当数组中任意元素为null/undefined时过滤整个数组,同时让TypeScript能自动识别数组每个元素的非nullish类型,适配combineLatest这类返回数组的操作符链。
修改后的完整实现
import { Observable, UnaryFunction, pipe, filter } from 'rxjs'; // 类型别名:将数组的每个元素转换为非nullish类型 type NonNullishArray<T extends readonly any[]> = { [K in keyof T]: NonNullable<T[K]> }; // 基础类型守卫:判断单个值是否非nullish function isNonNullish<T>(value: T | null | undefined): value is NonNullable<T> { return value != null; } // 数组类型守卫:判断数组所有元素是否都非nullish function isArrayOfNonNullish<T extends readonly any[]>( value: T | null | undefined ): value is NonNullishArray<T> { return Array.isArray(value) && value.every(isNonNullish); } // 重载filterNullish的函数签名,适配单个值和数组两种场景 export function filterNullish<T>(): UnaryFunction< Observable<T | null | undefined>, Observable<NonNullable<T>> >; export function filterNullish<T extends readonly any[]>(): UnaryFunction< Observable<T | null | undefined>, Observable<NonNullishArray<T>> >; // 实现逻辑 export function filterNullish<T>(): UnaryFunction< Observable<T | null | undefined>, Observable<T extends readonly any[] ? NonNullishArray<T> : NonNullable<T>> > { return pipe( filter((value): value is T extends readonly any[] ? NonNullishArray<T> : NonNullable<T> => { return Array.isArray(value) ? isArrayOfNonNullish(value) : isNonNullish(value); }) ); }
用法示例
1. 单个值场景(原有功能保留)
obs$ = this.store.select(selectSomething).pipe( filterNullish(), // 此处something类型已自动排除null/undefined map((something) => this.createOtherThing(something)) );
2. 数组场景(新增功能)
combineLatest([this.something$, this.otherthing$]).pipe( filterNullish(), tap(([something, otherthing]) => { // TypeScript自动识别something和otherthing均为非nullish类型,可安全操作 console.log(something.id, otherthing.name); }) );
关键实现细节
- 类型推导优化:通过
NonNullable<T>处理单个值的非nullish类型,NonNullishArray<T>映射数组元素的非nullish类型,确保TypeScript能准确推断输出类型。 - 重载函数签名:为单个值和数组分别定义函数签名,让TS根据输入Observable的类型自动匹配对应的输出类型。
- 过滤逻辑:对数组额外做
every检查,确保所有元素都非nullish才保留,否则过滤掉整个数组。
内容的提问来源于stack exchange,提问作者RobSeg
相关产品推荐
相关产品推荐

