Angular升级至6+后rxjs map管道出现'this'上下文类型不匹配问题
解决Angular 6+中Observable 'this'上下文类型不匹配问题
这个类型错误其实是RxJS操作符的上下文绑定和类型推断搞出来的小麻烦,我来帮你捋捋问题根源,再给你几个可行的修复方案:
问题到底出在哪?
你的代码里,catchError((err) => this.handleError(err)) 乍一看没啥问题,但TypeScript做类型检查时,会误以为handleError执行时的this是Observable类型,而不是你的服务类本身。再加上map操作返回的数组没明确标注类型,类型推断就跑偏了,最终和toPromise<[Category, ProductList]>的类型要求对不上,就抛出了这个错误。
修复方案
方案1:明确类型+保留正确的this上下文
首先得确保handleError返回的Observable类型和上游的一致,同时用箭头函数包裹来锁定this指向你的服务类,另外给map加上明确的类型标注,帮TypeScript理清思路:
getStartpageCategoryWithProducts(startpagePosition, pageSize?: number, page?: number): Promise<[Category, ProductList]> { let params = new HttpParams(); if(pageSize) { params = params.append('pageSize', pageSize.toString()); } if(page) { params = params.append('page', page.toString()); } const options = { params }; const url = `catalog/categories/startpagePosition/${startpagePosition}`; return this.http.get(url, options).pipe( // 明确告诉TypeScript,这里要把unknown类型转成目标数组类型 map<unknown, [Category, ProductList]>(res => [res['category'], this.extractData(res['searchResult'])]), // 用箭头函数确保this指向当前类,同时指定handleError的返回类型 catchError((err) => this.handleError(err) as Observable<[Category, ProductList]>) ).toPromise(); }
方案2:提前绑定handleError的this
如果你不想在catchError里写箭头函数,可以在类的构造函数里提前把handleError的this绑定到当前类:
constructor(private http: HttpClient) { // 把handleError的this固定为当前服务类 this.handleError = this.handleError.bind(this); } // 之后在pipe里直接传handleError就行 getStartpageCategoryWithProducts(startpagePosition, pageSize?: number, page?: number): Promise<[Category, ProductList]> { // ... 其他代码和之前一样 return this.http.get(url, options).pipe( map<unknown, [Category, ProductList]>(res => [res['category'], this.extractData(res['searchResult'])]), catchError(this.handleError) ).toPromise(); }
额外的小优化
- 注意
HttpParams的append方法只接受字符串参数,所以如果pageSize和page是数字类型,记得转成字符串(我在方案1里已经加上了toString()) - 用模板字符串拼接URL比加号更清爽,也不容易出错
- 如果你的
handleError是通用的错误处理方法,可以改成泛型方法,这样用起来更灵活:
handleError<T>(error: HttpErrorResponse): Observable<T> { // 这里写你的错误处理逻辑,比如打印错误、返回默认值等 return throwError(() => new Error('请求出错啦')) as Observable<T>; }
之后用的时候直接写catchError(err => this.handleError<[Category, ProductList]>(err)),类型检查会更严谨。
内容的提问来源于stack exchange,提问作者Mackelito
相关产品推荐
相关产品推荐

