升级 angular 5.2 到 6.0.7 后某些 HttpClient 服务中的 TS 2322

TS 2322 in some HttpClient services after upgrading angular 5.2 to 6.0.7

我正在使用 TypeScript ~2.7.0 更新到 Angular 6。在Angular 5.2.12中,我写了这样的服务方法:

isPartDraft = (part: number): Observable<boolean> =>
  this._http.get(`${this.rest}/isDraft/${part}`)
            .catch(MyPartService.handleError);

用 return 类型注释函数定义,但没有在函数体内断言其类型。

似乎不​​再可能在某些情况下,因为tsc提出:

TS2322:
Type 'Observable<Object>' is not assignable to type 'Observable<boolean>'.
  Type 'Object' is not assignable to type 'boolean'.

并且我被迫按照 current Angular documentation:

中的建议在函数体内断言 return 类型
isPartDraft = (part: number) =>
  this._http.get<boolean>(`${this.rest}/isDraft/${part}`)
      .pipe(catchError(MyService.handleError));

到目前为止一切顺利(自 angular2-rc6 以来我们从未更改过我们的注释,所以这可能已经潜伏了一段时间)。

但是在这些情况下我没有收到任何 TS 错误:

getPasswordPolicy(): Observable<PasswordPolicy> {
  return this._http.get(`${this.rest}/securityPolicy/`)
    .pipe(
      map((securityPolicy: any) => securityPolicy.passwordPolicy),
      catchError(error => observableThrowError(error))
    );
}

并且在不同的服务中:

getPartsAtDate = (id: number, date: string, time: string): Observable<number[]> =>
  this._http.get(`${this.rest}/partsOnDate/${id}/${date}/${time}`)
    .pipe(catchError(MyService.handleError));

getAllNewOrders = (id: number): Observable<Orders[]> =>
  this._http.get(`${this.rest}/${id}`)
    .pipe(catchError(MyService.handleError));

那么 pipe()catchError()map() 运算符是如何交互产生这种情况的呢?为什么我不能在第一种情况下注释函数定义,但在后三种情况下可以?

(当然,我可以自动修复 tsc 抛出错误的地方,但我更愿意了解发生了什么,尤其是相同的上下文似乎会产生不同的结果。)

根据要求,这是错误处理程序(每个服务中的实现是相同的):

private static handleError(error: any) {
  console.log('error ' + error);
  return observableThrowError(error.status || 'Server error');
}

方法 get 已重载,并非所有版本都使用泛型。根据您在第一个示例中调用 get 的方式,选择的签名是 returns Observable<Object>。如果你想要另一种可观察对象,你必须使用泛型(比如 get<boolean>)。

为什么其他示例有效?

map((securityPolicy: any) => securityPolicy.passwordPolicy),

在这里,您明确地将类型从 Observable<Object> 更改为 Observable< PasswordPolicy>。如果你有 map((securityPolicy: SecurityPolicy.

它就不会工作

catchError 不会像 map 那样改变可观察对象的类型。所以还是Observable<Object>.