Angular6+TypeScript2.7.2下Observable扩展报错求助
Angular 6 + TypeScript 2.7.2下Observable扩展失效的解决办法
最近把项目升级到Angular 6(搭配TypeScript 2.7.2)后,我之前写的Observable扩展方法safeSubscribe直接罢工了,报了两个头疼的错误:
'Observable'仅指类型,却被当作值使用。类型'Observable'上不存在属性'subscribe'。
先给大家看看我原来的代码:
import { Observable } from 'rxjs/Observable'; import { BaseComponent } from './base-component'; import { Subscription } from 'rxjs/Subscription'; import { Subscribable } from 'rxjs'; declare module 'rxjs/Observable' { export interface Observable<T> { safeSubscribe<T>(this: Observable<T>, component: BaseComponent, next?: (value: T) => void, error?: (error: T) => void, complete?: () => void): Subscription; } } export function safeSubscribe<T>(this: Observable<T>, component: BaseComponent, next?: (value: T) => void, error?: (error: T) => void, complete?: () => void): Subscription { let sub = this.subscribe(next, error, complete); component.markForSafeDelete(sub); return sub; } Observable.prototype.safeSubscribe = safeSubscribe;
问题根源
Angular 6配套的rxjs 6做了大规模的模块化重构,不仅导入路径变了,Observable的类结构和类型导出方式也有变化,再加上TypeScript 2.7的类型检查更严格,原来的扩展方式就不兼容了。
修正后的代码
// 注意:rxjs 6的导入路径是直接从rxjs导入 import { Observable, Subscription } from 'rxjs'; import { BaseComponent } from './base-component'; // 扩展rxjs模块里的Observable接口 declare module 'rxjs' { interface Observable<T> { safeSubscribe(this: Observable<T>, component: BaseComponent, next?: (value: T) => void, error?: (error: any) => void, complete?: () => void): Subscription; } } export function safeSubscribe<T>(this: Observable<T>, component: BaseComponent, next?: (value: T) => void, error?: (error: any) => void, complete?: () => void): Subscription { const sub = this.subscribe(next, error, complete); component.markForSafeDelete(sub); return sub; } // 这里要确保Observable是实际的类,而不是仅仅类型 Observable.prototype.safeSubscribe = safeSubscribe;
关键修改点
- 调整导入路径:rxjs 6中,Observable、Subscription这些核心类都直接从
rxjs导入,而不是原来的rxjs/Observable或rxjs/Subscription,这样我们才能拿到Observable的实际类对象,解决“仅指类型却被当作值使用”的错误。 - 修正模块声明范围:原来声明的是
rxjs/Observable模块,现在要改成rxjs模块,因为rxjs 6的Observable接口是在根模块rxjs里导出的,这样才能正确合并接口,解决“不存在subscribe属性”的问题。 - 修正error回调类型:原来的error回调参数类型是
T,这是错误的——subscribe的error回调接收的是错误对象,不是数据流的类型T,改成any或者你项目中定义的错误类型更合理。
内容的提问来源于stack exchange,提问作者Vova Bilyachat
相关产品推荐
相关产品推荐

