3

I'm trying to get my head around Reactive programming and observables, unsuccessfully of course. I have the following code:

this.searchSubscription = this.filtersSubject
  .takeLast(2)
  .reduce((acc, cur) => {
    console.log(acc);
    acc.push(cur);
    return acc;
  }, [])
  .debounceTime(1000)
  .subscribe(x => this.emitFilters());

I wanted to use takeLast(2) piped to reduce so I could turn it into an array of two values, and the filter is certain values between the two were different. I've been going over the docs for reduce, even passing a seed, but VS Code tells me that Property 'push' does not exist on type 'Object'. but the console.log shows acc to be an array. I'm baffled at what's going on and how to fix it. And of course, I may be tackling this problem entirely wrong, which is making observables hard enough to understand.

1 Answer 1

6

Your code is correct but there is a bug in rxjs5 that is preventing it from type checking.

Looking at the source code of reduce we see the following signature

export function reduce<T>(this: Observable<T>, accumulator: (acc: T, value: T, index: number) => T, seed?: T): Observable<T>;

export function reduce<T>(this: Observable<T>, accumulator: (acc: T[], value: T, index: number) => T[], seed?: T[]): Observable<T[]>;

export function reduce<T, R>(this: Observable<T>, accumulator: (acc: R, value: T, index: number) => R, seed?: R): Observable<R>;

When writing overloads in TypeScript it is necessary to order them from greatest to least specificity with respect to their types including their type arguments. This is because TypeScript picks the first matching overload. In this case, the last declaration in the overload set actually needs to be specified as the first.

I created https://github.com/ReactiveX/rxjs/issues/2339 because of this question.

Sign up to request clarification or add additional context in comments.

10 Comments

Thanks for the feedback. I'm having enough trouble wrapping my head around Reactive programming, stuff like this makes me think I'm getting it wrong... Which I probably still am. Do you know if I can get around this, or have to do something else in the mean time?
Also, you could avoid the bug and could simplify your code by using the toArray operator, instead. (And, as the observable completes, the debounceTime is redundant and just serves as a delay, as it will only ever see one value - the array.)
Without resorting to editing the source then there are few work arounds but they are fairly complicated. This is a pretty serious bug that should be fixed I'm surprised it hasn't been reported earlier. Perhaps it has.
@cartant that's a good point but the definition of reduce is clearly wrong as it is intending to provide for the use case where the accumulator is of a different type than the elements yielded by the observable but it's failing to do so.
@Aluan Yep. I agree with you. It's an RxJS bug to be avoided - not the OP's.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.