首页 > 解决方案 > 我如何说服 typescript 可以在主题上调用 Observable 运算符?

问题描述

示例代码,使用 Angular 4.1.3、rxjs 5.3.0、typescript 2.2.2:

import { Subject } from 'rxjs'

export class Example {
  public response$: Subject<boolean>;

  public confirm(prompt: string): Subject<boolean> {
    // ...set up a confirmation dialog...
    this.response$ = new Subject<boolean>();
    return this.response$.first();
  }
}

当我尝试编译这段代码时,打字稿抱怨最后一行:

The 'this' context of type 'Subject<boolean>' is not assignable to method's 'this' of type 'Observable<boolean>'.
  Types of property 'lift' are incompatible.
    Type '<R>(operator: Operator<boolean, R>) => Observable<boolean>' is not assignable to type '<R>(operator: Operator<boolean, R>) => Observable<R>'.
  Type 'Observable<boolean>' is not assignable to type 'Observable<R>'.
    Type 'boolean' is not assignable to type 'R'.

我的感觉是,这是说这first()是 Observable 的方法,而不是 Subject,但我的理解是 Subject 也是 Observable,所以这应该不是问题。而且,事实上,如果我忽略错误,代码编译并运行良好。

我尝试过的事情:

  1. 显式导入运算符的各种方式first,例如import 'rxjs/add/operator/first'. 这不会改变错误。
  2. 在调用之前将 Subject 转换为 Observable first(),例如return (this.response$ as Observable<boolean>).first();。这会导致一个不同但类似的错误,这对我来说似乎也不正确:Type 'Observable<boolean>' is not assignable to type 'Subject<boolean>'. Property 'observers' is missing in type 'Observable<boolean>'.

如何说服 typescript 调用first()主题是有效的?

澄清以下关于返回类型的讨论:该方法也可能有一个不正确的返回类型(应该是 Observable 而不是 Subject),但这似乎是一个单独的问题;更改返回类型并不能解决上述错误。进一步证实这一点的细节是,当 vscode 突出显示错误时,它只突出显示this.response$,而不是整个返回行,这表明问题出在this.response$and之间first(),而不是 between first()and 函数的签名:

vscode中突出显示的错误

标签: angulartypescriptrxjsrxjs5

解决方案


您对 Subject 也是 Observable 的理解是正确的,但在某种程度上,Subject 也可以用作 Observable。但这不会产生Subject一个Observable,反之亦然。

正如 ggradnig 所建议的那样,您应该将confirm函数的返回类型更改为,Observable<boolean>而不是Subject<boolean>因为上的first方法Subject<boolean>将返回一个Observable<boolean>

import { Subject } from 'rxjs'

export class Example {
  public response$: Subject < boolean > ;

  public confirm(prompt: string): Observable<boolean> {
    // ...set up a confirmation dialog...
    this.response$ = new Subject < boolean > ();
    return this.response$.first();
  }
}

推荐阅读