带有 RxJS 过滤器输入问题的 Typescript

Posted

技术标签:

【中文标题】带有 RxJS 过滤器输入问题的 Typescript【英文标题】:Typescript with RxJS filter typing problem 【发布时间】:2019-12-04 00:34:04 【问题描述】:

我刚刚从 typescript 2.4 升级到 3.2,现在使用未知类型,类型系统更加严格,这会触发一些我以前没有的错误。

所以我有一个效果,可以从存储中检索一些可能为空的数据,我想在调度我的下一个操作之前使用过滤器确保它不为空。

@Effect() saveSuccess$: Observable<Action> = this.actions$.pipe(
        ofType(actions.SAVE_SUCCESS),
        switchMapTo(this.store.pipe(select(selectors.getId))),
        filter((id: number | null) => id !== null),
        map((id: number) => new actions.GetData( Id ))
);

过滤器现在是红色的:

    Argument of type 'MonoTypeOperatorFunction<number | null>' is not assignable to parameter of type 'OperatorFunction<number | null, number>'.
  Type 'Observable<number | null>' is not assignable to type 'Observable<number>'.
    Type 'number | null' is not assignable to type 'number'.
      Type 'null' is not assignable to type 'number'.ts(2345)

我可以通过使用任何类型来绕过错误,但我觉得我不应该这样做。如果我将地图更改为接受number | null,它可以工作,但它没有任何意义,因为它正是过滤器的工作。

【问题讨论】:

【参考方案1】:

尝试通过添加返回类型id is number 将您的过滤器函数转换为类型保护。我知道这在过滤数组时有效,虽然我没有用 observables 测试它,但我希望它也可以在那里工作(因为他们用this type definition 定义了filter):

this.actions$.pipe(
  ofType(DCFActions.SAVE_SUCCESS),
  switchMapTo(this.store.pipe(select(selectors.getId))),
  filter((id: number | null): id is number => id !== null),
  map((id: number) => new actions.GetData( Id ))
);

如果您想创建一个更通用的过滤器函数来过滤掉更多事物中的空值,而不仅仅是数字,那么您可以这样写:

const notNull = <T>(value: T | null): value is T => value !== null;

// ... to be used like:
filter(notNull);

您可以在此处阅读有关用户定义类型保护的更多信息:https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards

【讨论】:

如果类型(此处:数字)未知,您也可以内联所有这些:filter(&lt;T&gt;(x: T | null): x is T =&gt; x !== null) 我真的很喜欢这个解决方案。太好了! notNull 实用功能很棒。谢谢。

以上是关于带有 RxJS 过滤器输入问题的 Typescript的主要内容,如果未能解决你的问题,请参考以下文章

在使用带有 Angular 的 FromEvent RxJS 订阅输入标签值更改时如何避免使用“任何”?

RxJs Observable:如果为空/过滤则执行函数

Rxjs 过滤器运算符不适用于 Angular2 Observable

RXJS Observable 数组上的简单过滤器

RxJS if-else 类似管道过滤

Angular使用总结 --- 搜索场景中使用rxjs的操作符