在Typescript中指定自定义RxJS运算符的签名

Jen*_*ger 3 rxjs typescript angular

以下自定义RxJS运算符(实际上只是演示的.filter等效运算符)当前在Angular 4.0.0-rc.2组件中声明.

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);
  });
};
Run Code Online (Sandbox Code Playgroud)

函数签名当前接受cmd为隐式any类型.我试图限制允许的类型,如下所示:

restrictToCommand<U>(f: (x: T | T[]) => U): Observable<U>;
Run Code Online (Sandbox Code Playgroud)

Observable.prototype.restrictToCommand = function (cmd: string | string[]) { ... }
Run Code Online (Sandbox Code Playgroud)

但是,似乎我无法覆盖提供的类型定义,因为这会导致以下编译器错误:

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'.)
Run Code Online (Sandbox Code Playgroud)

我错过了什么?

car*_*ant 6

当我定义自定义RxJS运算符时,我通常会这样做:

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;
  }
}
Run Code Online (Sandbox Code Playgroud)

我发现typeof在声明中使用合并可以简化事情.