angularrxjsobservablerxjs-observables

How to pass an array of pipable operators to pipe()?


[Angular 12]I have a service with a method, handleFormControlChanges, which accepts, a formControl, a destroy subject, a method and an array of pipable operators (e.g., delay), and I would like to apply them using pipe().

handleFormControlChanges<T>(
 formControl: FormControl,
 destroy$: Subject<void>,
 onValueChange: (value: T) => void,
 customOperators: Array<OperatorFunction<any, any>> = []
): void {

 formControl.valueChanges
  .pipe(
    ...customOperators,
    takeUntil(destroy$),
    tap(() => this.setLoading$(true))
  )
  .subscribe(onValueChange);
}

I can't just destructure an array like ...customOperators and pass it to pipe() as it causes this TypeScript error:

TS2575: No overload expects 2 arguments, but overloads do exist that expect either 2 or 4 arguments.

How can I pass the array of pipable operators to pipe()? How can I avoid this error?


Solution

  • I linked a potential duplicate, but for your specific use case, I'd just loop through the custom operators to compose the overall observable:

    handleFormControlChanges<T>(
      formControl: FormControl,
      destroy$: Subject<void>,
      onValueChange: (value: T) => void,
      customOperators: Array<OperatorFunction<any, any>> = []
    ): void {
    
      // Capture the initial observable.
      let composedChanges = formControl.valueChanges;
    
      // Apply each of the supplied custom operators.
      for (let op of customOperators) {
        composedChanges = composedChanges.pipe(op);
      }
    
      // Subscribe to the composed result.
      composedChanges
        .pipe(
          takeUntil(destroy$),
          tap(() => this.setLoading$(true))
        )
        .subscribe(onValueChange);
    }