首页 > 解决方案 > defer() 不再允许可观察的返回类型

问题描述

今天我从 angular 6 升级到 7

与此同时,我不得不将 rxjs 从 6.1.0 升级到 6.3.3,并将 typescript 从 2.7.2 升级到 3.1.1

现在这个 ngrx 效果方法抛出了一个打字稿错误:

  @Effect()
  init$ = defer(() => {
    const userData = localStorage.getItem('user');
    return (userData)
      ? of(new Login(JSON.parse(userData)))
      : of(new Logout());
  });

'() 类型的参数 => Observable | Observable' 不可分配给 '() => void | 类型的参数 订阅 | 订阅 | 承诺喜欢 | InteropObservable”。

似乎我不能再使用 defer 来调度这样的动作,所以我不确定如何编写初始化效果。

我只需要等待商店被初始化,所以在这个方法中我推迟执行,直到效果订阅了动作流。

有谁知道我该如何解决这个问题?

更新:

我还找到了一个利用Stackblitz的示例ROOT_EFFECTS_INIT,但由于我在一个功能模块中,这不起作用(在此处讨论

import { ROOT_EFFECTS_INIT } from '@ngrx/effects';

@Effect()
  init$ = this.actions$
    .ofType(ROOT_EFFECTS_INIT)
    .pipe(
      map(() => {
        const userData = localStorage.getItem('user');
        return (userData)
          ? of(new Login(JSON.parse(userData)))
          : of(new Logout())
      })
    );

标签: rxjsngrx-effects

解决方案


这是 TypeScript 的限制。您可以通过在箭头函数中显式指定返回类型来解决此问题:

@Effect()
init$ = defer((): Observable<Action> => { // HERE
  const userData = localStorage.getItem('user');
  return (userData)
    ? of(new Login(JSON.parse(userData)))
    : of(new Logout());
});

或者,更具体地说:

@Effect()
init$ = defer((): Observable<Login | Logout> => { // HERE
  const userData = localStorage.getItem('user');
  return (userData)
    ? of(new Login(JSON.parse(userData)))
    : of(new Logout());
});

问题是没有显式返回类型,箭头函数的返回类型被推断为:

Observable<Login> | Observable<Logout>

而不是:

Observable<Login | Logout>

有趣的是,虽然它确实是 TypeScript 的限制,但这个 RxJS PR会解决问题,并且会看到推断出的正确类型。


推荐阅读