打字稿功能重载不兼容

时间:2020-04-27 21:32:56

标签: typescript rxjs ngrx

我一直在实施NgRx存储,发现自己使用了模式

 concatMap(action => of(action).pipe(
          withLatestFrom(this.store.pipe(select(fromBooks.getCollectionBookIds)))
        )),

(从https://ngrx.io/guide/effects的底部开始)

考虑到它可以占用多少空间,我想写一个方便的实用程序来处理它。

所以我想出了一个应该起作用的实现:

export function concatMapLatestFrom<A extends Action>(
    ...xs: Array<ObservableInput<never>>
): OperatorFunction<A, unknown> {
    return function (source: Observable<A>): Observable<unknown> {
        return source.pipe(
            concatMap((action) => of(action).pipe(withLatestFrom(...xs))),
        );
    };
}

我写了一些正确类型的重载:

export function concatMapLatestFrom<X1, A extends Action>(
    source1: ObservableInput<X1>,
): { (source1: X1): OperatorFunction<A, [A, X1]> };

export function concatMapLatestFrom<X1, X2, A extends Action>(
    source1: ObservableInput<X1>,
    source2: ObservableInput<X2>,
): { (source1: X1, source2: X2): OperatorFunction<A, [A, X1, X2]> };

export function concatMapLatestFrom<X1, X2, X3, A extends Action>(
    source1: ObservableInput<X1>,
    source2: ObservableInput<X2>,
    source3: ObservableInput<X3>,
): {
    (source1: X1, source2: X2, source3: X3): OperatorFunction<
        A,
        [A, X1, X2, X3]
    >;
};

但是出于某种原因,它认为重载签名与实现不兼容。如果我注释掉其中之一,则会重复显示下一行。

这使我逃避了这实际上是什么问题,对于编译器来说,为什么不兼容是一件好事,但是不幸的是它没有提供任何细节。

2 个答案:

答案 0 :(得分:1)

我认为罪魁祸首是您在此处使用的neverunknown类型。

所以,如果有

of(1)
  .pipe(
    concatMapLatestFrom(of('john'), of(true))
  ).subscribe(observer)

然后,如果我理解正确,observer应该收到一个[number, string, boolean]元组。

据我所知,concatMapLatestFrom说得不是很清楚:

function concatMapLatestFrom (): OperatorFunction<A, unknown> {}

因此,我们只有该元组的第一个元素,即源的类型。剩下要做的就是根据提供给ObservableInput的{​​{1}}的类型来推断其他类型。

请记住,这就是我的方法:

concatMapLatestFrom

使用的类型可以从export function concatMapLatestFrom< A extends Action, U extends Array<ObservableInput<any>>, R = Unshift<ObservedValueTupleFromArray<U>, A> > ( ...xs: U ): OperatorFunction<A, R> { return function (source: Observable<A>): Observable<R> { return source.pipe( concatMap((action) => of(action).pipe(withLatestFrom(...xs))), ); }; } 导出:

'rxjs'

Source

答案 1 :(得分:0)

使用重载时,类型信息来自重载,实现只需要处理所有可能的参数。类型参数和返回类型将根据选定的重载进行更改,因此,将其遗漏可能会解决此问题。

export function concatMapLatestFrom(
  ...xs: Array<ObservableInput<never>>
) {
  return function(source: Observable<any>): Observable<unknown> {
    return source.pipe(
      concatMap(action => of(action).pipe(withLatestFrom(...xs)))
    );
  };
}