typescript 过滤器未定义从RxJS Observable

unguejic  于 2023-06-24  发布在  TypeScript
关注(0)|答案(6)|浏览(153)

是否有特定的习惯用法或实用程序用于从RxJS可观察数据中过滤undefined?这段代码有我想要的行为:

obs.pipe(filter(x => x !== undefined))

一些替代方案是

obs.pipe(filter(x => x)) // for all falsy values

obs.pipe(filter(Boolean)) // for falsy variables using Boolean ctor
oxosxuxt

oxosxuxt1#

严格地说,单独使用过滤器来删除未定义的值并不能满足您需要的所有要求。它过滤掉未定义的值,但不更改类型以指示undefined不再是可能的值。
在示例中:

const obs = new Subject<string | undefined>;
const stringObs = obs.pipe(filter(x => x !== undefined))

stringObs可观测值仍然具有Observable<string | undefined>类型。
要解决这个问题,你需要用途:

const stringObs = obs.pipe(filter(x => x !== undefined) as OperatorFunction<string | undefined, string>)

只有当你使用严格的空检查时,这才是真正的问题,但是如果你这样做了(并且可以说你应该这样做),那么创建一个自定义操作符突然变得更有意义了!就像

function filterNullish<T>(): UnaryFunction<Observable<T | null | undefined>, Observable<T>> {
  return pipe(
    filter(x => x != null) as OperatorFunction<T | null |  undefined, T>
  );
}

做的工作。
然后,您可以用途:

const stringObs = obs.pipe(filterNullish())

并且stringObs的类型将是Observable<string>。Typescript能够正确推断T的类型,这给我留下了深刻的印象。

vxf3dgd4

vxf3dgd42#

为了帮助typescript理解未定义的值已被删除,一种方法是create a custom operator。另一种方式是通过用户定义的类型保护。

function isDefined<T>(arg: T | null | undefined): arg is T extends null | undefined ? never : T {
  return arg !== null && arg !== undefined;
}

const obs = from(['hello', null, undefined]);
const filtered: Observable<string> = obs.pipe(filter(isDefined));
egdjgwm8

egdjgwm83#

Rxjs操作符被认为是低级的,旨在以一种可读的方式组合在一起,以创建一个您可以预测地使用的结果观察对象。让一个“实用程序”为你做到这一点并不完全是我(谦虚地)称之为“rxjs方式”。如果你所说的“习语”是指一种约定,那么你的代码示例基本上就是你要寻找的。
我自己也经常使用这种过滤模式,甚至考虑过创建一个自定义操作符;然而,与此相反:

obs.pipe(filter(x => x !== undefined))

你会得到这样的结果:

obs.pipe(notUndefined()) // or hasValue() or whatever you want to name it...

这里没有太多的储蓄。我认为你甚至没有在可读性上得到节省(或者完全是微不足道的),这就是为什么我从来没有抽出时间来做这件事。另一个不使用的理由是,过滤布尔值也很常见,然后开始让你想知道是否应该将两者结合起来,以避免太多令人困惑的/类似的操作符,所有这些操作符都可以轻松地使用filter创建,等等。
长话短说,我已经考虑了这个确切的问题很多,并认为您只需使用您提供的代码示例即可。这是“正确的”。是rxjs y是可读的。

lh80um4z

lh80um4z4#

我想我说得对,你可以用途:
obs.pipe(filter(x => x))
也是一样的:
(过滤器(x => x!== null && x!== undefined))

kpbwa7wx

kpbwa7wx5#

由于最新版本的typescript期望 predicate 为boolean,因此它不支持以前的falsy过滤器,如:

filter(x => x)

在这种情况下,您可能需要用途:

filter(x => !!x)
hzbexzde

hzbexzde6#

注:用于生产开源项目。

步骤1:使用isNonNullable

readonly filePath$ = this.pickFilesResult$.pipe(
    map((pickMediaResult) => pickMediaResult.files[0]?.path),
    isNonNullable()
);

步骤2:在项目中添加src/utils/rx-operators.ts

import { Observable, filter } from 'rxjs';

export function isNonNullable<T>() {
  return (source$: Observable<null | undefined | T>) =>
    source$.pipe(
      filter((v): v is NonNullable<T> => v !== null && v !== undefined)
    );
}

相关问题