Angular 6 & rxjs6 - 管道运算符 - 类型 'Observable<>' 不提供签名匹配

Angular 6 & rxjs6 - piped operators - Type 'Observable<>' provides no match for the signature

我有一个搜索功能,在版本 6 之前的 Angular 中是这样写的:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Observable, Subject } from 'rxjs/Rx';

import { Product } from '../products/product';
import { ProductService } from '../products/product.service';
import { Subscription } from 'rxjs';
import { SearchService } from '../services/search-service';
import { Router } from '@angular/router';
import { PagedList } from '../shared/paged-list.interface';

@Component({
  selector: 'fb-product-list',
  templateUrl: './product-list.component.html'
})
export class ProductListComponent implements OnInit, OnDestroy {
  total$: Observable<number>;
  items$: Observable<Product[]>;

  product: Product;
  subTimer: Subscription;

  term: string = "";
  currentPage: number = 1;
  private pageStream = new Subject<number>();

  public pluralizeMapProduct: any = {
    '=0': 'No products',
    '=1': '1 product',
    'other': '# products'
  }

  constructor(
    private _searchService: SearchService,
    private _productService: ProductService,
    private _router: Router) {
  }

  ngOnInit() {
    this.setupSearching();
  }

  setupSearching(){
    const searchSource = this._searchService.searchTermStream
      .map(searchTerm => {
        this.term = searchTerm;
        return {search: searchTerm, page: 1}
      });

    const pageSource = this.pageStream.map(pageNumber => {
      this.currentPage = pageNumber;
      return {search: this.term, page: pageNumber}
    });

    const source:Observable<PagedList<any>> = pageSource
      .merge(searchSource)
      .startWith({search: this.term, page: this.currentPage})
      .switchMap((params: {search: string, page: number}) => {
        return this._productService.getProductsPaged(params.search, params.page, null, null)
      })
      .share();

    this.total$ = source.pluck('meta').pluck('total_count') as Observable<number>;
    this.items$ = source.pluck('data') as Observable<Product[]>;
  }

  goToPage(page: number, reload: boolean) {
    this.pageStream.next(page);
  }  

}

现在按照以下指南重写:

    import { Component, OnInit, OnDestroy } from '@angular/core';
    import { Subscription, Observable, Subject, merge } from 'rxjs';
    import { map, startWith, switchMap, share, pluck } from 'rxjs/operators';

    import { Product } from '../products/product';
    import { ProductService } from '../products/product.service';
    import { SearchService } from '../services/search-service';
    import { Router } from '@angular/router';
    import { PagedList } from '../shared/paged-list.interface';
    import { SearchSpec } from '../shared/search-spec.interface';

    @Component({
      selector: 'fb-product-list',
      templateUrl: './product-list.component.html'
    })
    export class ProductListComponent implements OnInit, OnDestroy {
      total$: Observable<number>;
      items$: Observable<Product[]>;

      product: Product;
      subTimer: Subscription;

      term: string = "";
      currentPage: number = 1;
      private pageStream = new Subject<number>();

      public pluralizeMapProduct: any = {
        '=0': 'No products',
        '=1': '1 product',
        'other': '# products'
      }

      constructor(
        private _searchService: SearchService,
        private _productService: ProductService,
        private _router: Router) {
      }

      ngOnInit() {
        this.setupSearching();
      }

      setupSearching(){
        const searchSource = this._searchService.searchTermStream
          .pipe(
            map(searchTerm => {
              this.term = searchTerm;
              return {term: searchTerm, page: 1} as SearchSpec
            })
          );

        const pageSource = this.pageStream
          .pipe(
            map(pageNumber => {
              this.currentPage = pageNumber;
              return {term: this.term, page: pageNumber} as SearchSpec
            })
          );

        const source:Observable<PagedList<any>> = pageSource
          .pipe(        
            merge(searchSource),
            startWith({term: this.term, page: this.currentPage}),
            switchMap((params: {term: string, page: number}) => {
              return this._productService.getProductsPaged(params.term, params.page, null, null)
            }),
            share()
          );

        this.total$ = source.pipe(pluck('meta'), pluck('total_count')) as Observable<number>;
        this.items$ = source.pipe(pluck('data')) as Observable<Product[]>;
      }

      goToPage(page: number, reload: boolean) {
        this.pageStream.next(page);
      }  

    }

VSCode 抱怨管道内第三个常量中的这一行:

merge(searchSource),

错误:

Argument of type 'Observable' is not assignable to parameter of type 'OperatorFunction'.

Type 'Observable' provides no match for the signature '(source: Observable): Observable<{}>'

我有点理解(这是一个参数不匹配,因为在 rxjs6 中我们必须使用 OperatorFunctions)但我不知道如何修复它。


编辑

这是搜索服务(针对 v6):

import { Injectable } from '@angular/core';

import { Subject } from 'rxjs';

@Injectable()
export class SearchService {

  searchTermStream = new Subject<string>();

  sendSearchTerm(term: string) {
    this.searchTermStream.next(term)
  }

}

这是我为强制输入而添加的新接口 SearchSpec:

export interface SearchSpec {
  term: string,
  page: number
}

你只需要改变导入,它实际上应该是:

import { merge } from 'rxjs/operators';

operators 导入的是 instance method,似乎可以解决您的问题。

import { merge } from 'rxjs/operators';

合并已弃用:弃用以支持静态合并。 (弃用)版本 rxjs6