简体   繁体   English

将Angular和RxJS 5迁移到6之后的错误-类型'Observable <{}>'无法分配给类型'Observable <…>'

[英]Errors after migrated Angular and RxJS 5 to 6 - Type 'Observable<{}>' is not assignable to type 'Observable<…>'

I migrated an Angular project from v5 to v6. 我将Angular项目从v5迁移到v6。

In order to update all the imports I already ran rxjs-5-to-6-migrate : 为了更新所有导入,我已经运行了rxjs-5-to-6-migrate

npm install -g rxjs-tslint
rxjs-5-to-6-migrate -p src/tsconfig.app.json

But now I have ERRORs like the following: 但是现在我有如下错误:

src/app/products/product.service.ts(54,4): error TS2322: Type 'Observable<{}>' is not assignable to type 'Observable<{ count: number; next: string; previous: string; results: any[]; }>'.
  Type '{}' is not assignable to type '{ count: number; next: string; previous: string; results: any[]; }'.
    Property 'count' is missing in type '{}'.

product.service.ts : product.service.ts

import { Injectable } from '@angular/core';
//import { Http, Response, Headers, RequestOptions } from '@angular/http';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { ErrorObservable } from 'rxjs/observable/ErrorObservable';

import { catchError, map, tap, finalize } from 'rxjs/operators';

import { Product } from './product';

import { SpinnerService } from './../utilities/spinner/spinner.service';

import { environment } from '../../environments/environment';

const endpoint = environment.apiHost+'/api/products/' //'http://127.0.0.1:8000/api/products/'

@Injectable()
export class ProductService {

  /* Caching few data that does not change so often */
  private productTypes: any[];
  private departments: any[];
  private authors: any[];
  private colors: any[];
  private sizeRuns: any[];

  constructor(private http: HttpClient, private _spinnerService: SpinnerService) { }

  list(params?): Observable<{count:number, next:string, previous:string, results: any[]}> {
    return this.http.get<{count:number, next:string, previous:string, results: any[]}>(endpoint, {params: params})
      .pipe(
        catchError(this.handleError<any>('Retrieving products'))
      );
  }

  /**
   * Handle Http operation that failed.
   * Let the app continue.
   * @param operation - name of the operation that failed
   * @param result - optional value to return as the observable result
   */
  private handleError<T>(operation='Operation', result?: T) {
    return (error: any): ErrorObservable | Observable<T> => {

      // TODO: send the error to remote logging infrastructure
      console.error(error); // log to console instead

      // TODO: better job of transforming error for user consumption
      console.log(`${operation} failed: ${error.message}`);

      // Let the app keep running by returning an Observable with empty result.
      //return of(result as T); 
      return new ErrorObservable(error);
    };
  }

}

I saw other questions like this on StackOverflow, but still I don't understand how to solve. 我在StackOverflow上看到了类似的其他问题,但我仍然不知道如何解决。 I can probably change the interface {count:number, next:string, previous:string, results: any[]} to simply any , but I don't really want to do it. 我可能可以将接口{count:number, next:string, previous:string, results: any[]}更改为any ,但是我真的不想这样做。 Any solution? 有什么办法吗?

UPDATE1 : Using an Interface UPDATE1 :使用接口

interface PaginatedList {
  count: number;
  next: string;
  previous: string;
  results: any[];
}

@Injectable()
export class ProductService {

  /* Caching few data that does not change so often */
  private productTypes: any[];
  private departments: any[];
  private authors: any[];
  private colors: any[];
  private sizeRuns: any[];

  constructor(private http: HttpClient, private _spinnerService: SpinnerService) { }

  list(params?): Observable<PaginatedList> {
    this._spinnerService.show('productListSpinner');
    return this.http.get<PaginatedList>(endpoint, {params: params})
      .pipe(
        catchError(this.handleError<any>('Retrieving products')),
        finalize(() => this._spinnerService.hide('productListSpinner'))
      );
  }

  /**
   * Handle Http operation that failed.
   * Let the app continue.
   * @param operation - name of the operation that failed
   * @param result - optional value to return as the observable result
   */
  private handleError<T>(operation='Operation', result?: T) {
    return (error: any): ErrorObservable | Observable<T> => {

      // TODO: send the error to remote logging infrastructure
      console.error(error); // log to console instead

      // TODO: better job of transforming error for user consumption
      console.log(`${operation} failed: ${error.message}`);

      // Let the app keep running by returning an Observable with empty result.
      //return of(result as T); 
      return new ErrorObservable(error);
    };
  }

}

ERRORS : 错误

src/app/products/product.service.ts(61,4): error TS2322: Type 'Observable<{}>' is not assignable to type 'Observable<PaginatedList>'.
  Type '{}' is not assignable to type 'PaginatedList'.
    Property 'count' is missing in type '{}'.

UPDATE2 : UPDATE2

Checking my errors, I think that ErrorObservable is causing the other errors: 检查我的错误,我认为ErrorObservable导致了其他错误:

src/app/products/product.service.ts(325,26): error TS2314: Generic type 'ErrorObservable<T>' requires 1 type argument(s).

I can probably change the interface {count:number, next:string, previous:string, results: any[]} to simply any` 我可能可以将接口{count:number,next:string,previous:string,results:any []}更改为any。

By doing this you would simply shot yourself on the foot. 通过这样做,您只需将自己打到脚上即可。 Why wouldn't you define the interface of a concept that you know? 您为什么不定义您所知道的概念的接口?

The first question that you should ask yourself when handling the error: do I need to gracefully or ungracefully handle it? 我需要正常笨拙地处理:处理错误时,你应该问自己的第一个问题?

Gracefully handling the error would transform it into a "fake" notification in the stream, keeping the type contract of it in most cases. 优雅地处理错误将其转换成一个“假”通知流中,保持它在大多数情况下,合同类型。 For example: 例如:

import { throwError, of } from 'rxjs';
import { catchError } from 'rxjs/operators';
// Create source Observable<string> that emits an error
const source : Observable<string> = throwError('This is an error!');
// Gracefully handle error, returning observable with error message
// Notice that the type contract of the source is mantained
const example : Observable<string> = source.pipe(catchError(val => of(`I caught: ${val}`)));
// Output: 'I caught: This is an error'
// Notice that the next, and not the error callback, is invoked
const subscribe = example.subscribe(
      val => console.log(val), 
      error => console.log("Something exploded: ", error));

In the previous example, I keep the type contract of the source. 在前面的示例中,我保留了源代码的类型协定。 In the following I dont: 在下面,我不:

import { throwError, of } from 'rxjs';
import { catchError } from 'rxjs/operators';
// Create source Observable<string> that emits an error
const source : Observable<string> = throwError('This is an error!');
// Gracefully handle error, returning observable with error message
// Notice that by mapping the error to a fake notification of another type, the new
// stream extends the type contract of the source
const example : Observable<string | number> = source.pipe(catchError(val => of(1)));
// Output: 'I caught: This is an error'
// Notice that the next, and not the error callback, is invoked
const subscribe = example.subscribe(
      val => console.log(val), 
      error => console.log("Something exploded: ", error));

The other option is to ungracefully handle an error, by basically applying some logic and then re-throwing. 另一种选择是,以非正常处理错误,通过基本上应用一些逻辑,然后重新投掷。 In such case, the type contract of the stream has no information about the error that the stream could arise . 在这种情况下, 流的类型协定不包含有关流可能出现的错误的信息 For example: 例如:

import { throwError, of } from 'rxjs';
import { catchError } from 'rxjs/operators';
// Create source Observable<string> that emits an error
const source : Observable<string> = throwError('This is an error!');
// Ungracefully handle error, re-throwing an object
const example : Observable<string> = source.pipe(catchError(error => throwError({message: 'Error caught', error})));
// Output: 'Something exploded: '
// Notice that the error, and not the next callback, is invoked
const subscribe = example.subscribe(
      val => console.log(val), 
      error => console.log("Something exploded: ", error));

Back to your issue; 回到您的问题; as it is, your approach is currently gracefully handling the error and extending the type contract of the source stream, without correctly declaring the return type of the method. 实际上,您的方法当前正在适当地处理错误并扩展源流的类型协定,而没有正确声明方法的返回类型。

The solution to the error would be to change the signature of the method to: 该错误的解决方案是将方法的签名更改为:

list(params?): Observable<PaginatedList | any>;

Another problem is that you are directly using ErrorObservable , which is indeed an implementation detail. 另一个问题是您直接使用ErrorObservable ,这确实是实现细节。 Normally you would use the throwError operator. 通常,您将使用throwError运算符。

您可以定义“或”运算符。

Observable<{count:number, next:string, previous:string, results: any[]}> |  Observable<any>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 角度6 - Rxjs 6 - 类型可观察 <Object> 不能分配给Observable类型 <Item> - Angular 6 - Rxjs 6 - Type Observable<Object> is not assignable to type Observable<Item> 输入“可观察的<subscription> ' 不可分配给 Observable 类型<mydata> rxjs angular</mydata></subscription> - Type 'Observable<Subscription>' is not assignable to type Observable<MyData> rxjs angular 类型&#39;Observable &lt;{}&gt;&#39;不能分配给&#39;Observable&#39;类型 <Item[]> :Rxjs - Type 'Observable<{}>' is not assignable to type 'Observable<Item[]>: Rxjs Rxjs 类型 Observable<Unknown> 不可分配给 Observable<void> - Rxjs type Observable<Unknown> is not assignable to Observable<void> 类型“可观察” <any> 无法使用rxjs5分配给angular2中的类型&#39;JSON&#39; - Type 'Observable<any>' is not assignable to type 'JSON' in angular2 with rxjs5 类型\\&#39;Observable &lt;{}&gt; \\&#39;不能指定为在角度2中键入 - Type \'Observable<{}>\' is not assignable to type in angular 2 RxJs - 类型'可观察<void> ' 不可分配给类型 'Observable<group[]> '</group[]></void> - RxJs - Type 'Observable<void>' is not assignable to type 'Observable<Group[]>' 不可分配给“可观察”类型 <task> &#39;。角4 - is not assignable to type 'Observable<task>'.Angular 4 rxjs管道:Observable类型的参数无法分配给参数 - rxjs pipes: Argument of type Observable not assignable to parameter 类型Observable &lt;{} | AppUser&gt;不可分配给 <AppUser> RxJS的运算符 - Type Observable<{} | AppUser> is not assignable to <AppUser> RxJS Of operator
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM