带有 RxJS 过滤器打字问题的 Typescript

ukn*_*ukn 6 rxjs typescript ngrx angular

我刚刚从 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 }))
);
Run Code Online (Sandbox Code Playgroud)

过滤器现在是红色的说:

    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)
Run Code Online (Sandbox Code Playgroud)

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

Nic*_*wer 16

尝试通过添加返回类型将过滤器函数变成类型保护id is number。我知道这在过滤数组时有效,虽然我没有用 observables 测试它,但我希望它也能在那里工作(因为它们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 }))
);
Run Code Online (Sandbox Code Playgroud)

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

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

// ... to be used like:
filter(notNull);
Run Code Online (Sandbox Code Playgroud)

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