[英]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.