3

The following custom RxJS operator (actually just a .filter equivalent for demonstration) is currently declared in an Angular 4.0.0-rc.2 component.

declare module 'rxjs/Observable' {
  interface Observable<T> {
    restrictToCommand<U>(f: (x: T) => U): Observable<U>;
  }
}

Observable.prototype.restrictToCommand = function (cmd) {
  return new Observable((observer) => {
    const obs = {
      next: (x) => {
        if (x.command === cmd || cmd.indexOf(x.command) !== -1) {
          observer.next(x);
        }
      },
      error: (err) => observer.error(err),
      complete: () => observer.complete()
    };
    return this.subscribe(obs);
  });
};

The function signature currently accepts cmd as implicit any type. I am attempting to restrict the allowed types like this:

restrictToCommand<U>(f: (x: T | T[]) => U): Observable<U>;

and

Observable.prototype.restrictToCommand = function (cmd: string | string[]) { ... }

However, it seems like I cannot overwrite the type definition supplied, as this causes the following compiler error:

ERROR in (...)/mycomponent.component.ts (11,1): Type '(cmd: string | string[]) => Observable<{}>' is not assignable to type '<U>(f: (x: any) => U) => Observable<U>'.
  Types of parameters 'cmd' and 'f' are incompatible.
    Type '(x: any) => any' is not assignable to type 'string | string[]'.
      Type '(x: any) => any' is not assignable to type 'string[]'.
        Property 'push' is missing in type '(x: any) => any'.)

What am I missing?

1 Answer 1

6

When I define custom RxJS operators, I usually do it something like this:

import { Observable } from 'rxjs/Observable';

function restrictToCommand<T>(
  this: Observable<T>,
  cmd: string | string[]
): Observable<T> {

  return new Observable((observer) => {
    const obs = {
      next: (x) => {
        if (x.command === cmd || cmd.indexOf(x.command) !== -1) {
          observer.next(x);
        }
      },
      error: (err) => observer.error(err),
      complete: () => observer.complete()
    };
    return this.subscribe(obs);
  });
}

Observable.prototype.restrictToCommand = restrictToCommand;

declare module 'rxjs/Observable' {
  interface Observable<T> {
    restrictToCommand: typeof restrictToCommand;
  }
}

I find that using typeof in the declaration merging simplifies things.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.