Ricardo Rocha
Ricardo Rocha

Reputation: 16236

RxJS6: Why observable Pipe operator only receives OperatorFunction and not MonoTypeOperatorFunction

I'm trying to understand the pipe operator of observable API:

 export declare class Observable<T> implements Subscribable<T> {
.......
    pipe<A>(op1: OperatorFunction<T, A>): Observable<A>;
    pipe<A, B>(op1: OperatorFunction<T, A>, op2: OperatorFunction<A, B>): Observable<B>;
    pipe<A, B, C>(op1: OperatorFunction<T, A>, op2: OperatorFunction<A, B>, op3: OperatorFunction<B, C>): Observable<C>;
    pipe<A, B, C, D>(op1: OperatorFunction<T, A>, op2: OperatorFunction<A, B>, op3: OperatorFunction<B, C>, op4: OperatorFunction<C, D>): Observable<D>;
    pipe<A, B, C, D, E>(op1: OperatorFunction<T, A>, op2: OperatorFunction<A, B>, op3: OperatorFunction<B, C>, op4: OperatorFunction<C, D>, op5: OperatorFunction<D, E>): Observable<E>;
    pipe<A, B, C, D, E, F>(op1: OperatorFunction<T, A>, op2: OperatorFunction<A, B>, op3: OperatorFunction<B, C>, op4: OperatorFunction<C, D>, op5: OperatorFunction<D, E>, op6: OperatorFunction<E, F>): Observable<F>;
    pipe<A, B, C, D, E, F, G>(op1: OperatorFunction<T, A>, op2: OperatorFunction<A, B>, op3: OperatorFunction<B, C>, op4: OperatorFunction<C, D>, op5: OperatorFunction<D, E>, op6: OperatorFunction<E, F>, op7: OperatorFunction<F, G>): Observable<G>;
    pipe<A, B, C, D, E, F, G, H>(op1: OperatorFunction<T, A>, op2: OperatorFunction<A, B>, op3: OperatorFunction<B, C>, op4: OperatorFunction<C, D>, op5: OperatorFunction<D, E>, op6: OperatorFunction<E, F>, op7: OperatorFunction<F, G>, op8: OperatorFunction<G, H>): Observable<H>;
    pipe<A, B, C, D, E, F, G, H, I>(op1: OperatorFunction<T, A>, op2: OperatorFunction<A, B>, op3: OperatorFunction<B, C>, op4: OperatorFunction<C, D>, op5: OperatorFunction<D, E>, op6: OperatorFunction<E, F>, op7: OperatorFunction<F, G>, op8: OperatorFunction<G, H>, op9: OperatorFunction<H, I>): Observable<I>;
.......
}

As you could see, all of pipe overload methods receive and OperationFunction type.

Lets check the filter operator API:

export declare function filter<T, S extends T>(predicate: (value: T, index: number) => value is S, thisArg?: any): OperatorFunction<T, S>;
export declare function filter<T>(predicate: (value: T, index: number) => boolean, thisArg?: any): MonoTypeOperatorFunction<T>;

As you can see, you have an overload method that returns an OperationFunction and another that returns MonoTypeOperatorFunction.

I have the following questions:

Upvotes: 4

Views: 3093

Answers (1)

Jota.Toledo
Jota.Toledo

Reputation: 28434

RxJS6 operators like filter, could only be used on pipe method?

Pipe methods are pure high-order functions. So no, they can be used as any other method. The difference being, that if you invoke them outside of a pipe closure, you will lose type intellisense.

Why in filter we have a overload method that return different types but the pipe only receives one?

Take the following with a grain of salt

Most operators/use cases in streams involve a transformation, eg transforming a value x from a domain X to a value y from a domain Y. This concept is abstracted by the definition of the OperatorFunction<X,Y> interface.

In the case of the filter operator, we have a specialized case of OperatorFunction<X,Y>, in which the condition X is Y and Y is X is fulfilled, as the operation takes a value x from the domain X and transforms it into a value y from the same domain X. This special case is once again abstracted by the MonoTypeOperatorFunction<X> interface, which is indeed defined as an extension of OperatorFunction<X,X>.

My guess is that the MonoTypeOperatorFunction interface was created with 2 goals:

  • Abstract the previously explained concept by defining a explicit interface
  • Keep the contract of pipe(...fn: OperatorFunction<X,Y>) by defining this interface as an extension of OperatorFunction

Upvotes: 4

Related Questions