Angular6 typescript extension method Observable<T>

Viewed 903

I am trying to do an extension method on Observable

import { Observable } from 'rxjs/Observable';

declare module 'rxjs/Observable' {
  interface Observable<T> {
    customFilter<T>(this: Observable<T>): Observable<T>;
  }
}

function customFilter<T>(this: Observable<T>) {
  return this;
}

Observable.prototype.customFilter = customFilter;

Howerver I am always getting a compilation error

ERROR in src/app/utils/observable.extensions.ts(13,1): error TS2693: 'Observable' only refers to a type, but is being used as a value here.

Here's my tsconfig.app.json

{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "outDir": "../out-tsc/app",
    "baseUrl": "./",
    "module": "es6",
    "types": [],
    "paths": {
      "@angular/*": [
        "../node_modules/@angular/*"
      ]
    }
  },
  "exclude": [
    "test.ts",
    "**/*.spec.ts"
  ]
}

Any idea ?

1 Answers

This is a subtle one. The rxjs/Observable module contains:

export * from 'rxjs-compat/Observable';

Your augmentation of an exported interface named Observable is blocking the export * statement from re-exporting Observable from rxjs-compat/Observable, just as if export interface Observable<T> { ... } had been written directly in the rxjs/Observable module. (Maybe the compiler should report an error when this happens. There was an issue open about this at one point, but it got closed without a clear statement about why the error couldn't be reported.) As a consequence, the only definition of Observable exported from rxjs/Observable is the interface in your augmentation; no value meaning is available.

The fix is to change your augmentation to target rxjs/internal/Observable (where the Observable class is originally declared) instead of rxjs/Observable, so that your interface properly merges with the original class.

Related