-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reduce with array input defaults the return type to an array of arrays #2519
Comments
/cc @aluanhaddad for visibility. |
@PrimalZed The issue you are experiencing comes from the type of |
@aluanhaddad the type from That error is the problem I'm experiencing, yes. The return type of Again, it's easily resolved by specifying some typing somewhere, but it seems like it should be able to pick it up. Maybe a type definition of |
@PrimalZed I see what you are getting at now. I hadn't noticed where map was being called when I looked earlier. The problem is actually that the wrong signature has now taking priority for nested arrays when the seed is an empty array. TLDR: your use case is covered by the general In other words the following typechecks import { Observable } from 'rxjs/Observable';
Observable.of([0, 1, 2, 3], [4, 5, 6, 7])
.reduce((acc, value) => acc.concat(value), [0])
.map(numbers => numbers.map(n => n++))
.subscribe(value => console.log(JSON.stringify(value))); while this, your example, does not import { Observable } from 'rxjs/Observable';
Observable.of([0, 1, 2, 3], [4, 5, 6, 7])
.reduce((acc, value) => acc.concat(value), [])
.map(numbers => numbers.map(n => n++))
.subscribe(value => console.log(JSON.stringify(value))); but it should. Removing the specialization function reduce<T>(
this: Observable<T>,
accumulator: (acc: T[], value: T, index: number) => T[],
seed: T[]
): Observable<T[]>; actually fixes type inference for your use case, but it may break others. I do not understand why the overload was even provided in the first place. For reference, it used to be specified as function reduce<T>(
this: Observable<T>,
accumulator: (acc: T[], value: T, index: number) => T[],
seed?: T[]
): Observable<T[]>; which was definitely wrong. The overload actually selected by your example in previous version was function reduce<T>(
this: Observable<T>,
accumulator: (acc: T, value: T, index: number) => T,
seed?: T
): Observable<T>; which is still present but the I think it should be removed altogether but I do not understand why it was added which is why I did not remove it. |
The overload was added so that common case of reduce to an array of // without the overload
Observable.of(0, 1, 2, 3)
.reduce((acc, value) => acc.concat(value), []); // [] would be {}[] and would require a cast to T[] to work correctly. It appears that reducing the precedence of the array variant we can get things to work. See the playground here or the code below. All that was done was that interface ObservableStatic {
of<T>(...args: T[]): Observable<T>;
}
interface Observable<T> {
map<T, R>(this: Observable<T>, project: (value: T, index: number) => R, thisArg?: any): Observable<R>;
subscribe(fn: Function);
reduce<T>(this: Observable<T>, accumulator: (acc: T, value: T, index: number) => T, seed?: T): Observable<T>;
reduce<T>(this: Observable<T>, accumulator: (acc: T[], value: T, index: number) => T[], seed: T[]): Observable<T[]>;
reduce<T, R>(this: Observable<T>, accumulator: (acc: R, value: T, index: number) => R, seed: R): Observable<R>;
}
let Observable: ObservableStatic;
Observable.of([0, 1, 2, 3], [4, 5, 6, 7])
.reduce((acc, value) => acc.concat(value), [])
.map(numbers => numbers.map(n => n++))
// .subscribe(value => console.log(JSON.stringify(value)));
Observable.of(0, 1, 2, 3, 4, 5, 6, 7)
.reduce((acc, value) => { acc.push(value); return acc; }, [])
.map(numbers => numbers.map(n => n++))
// .subscribe(value => console.log(JSON.stringify(value))); |
Thanks @david-driscoll, I was wondering if the type definitions worked as a "pick first matching" sort of thing. So all we have to do is change the order of the type definitions. |
@david-driscoll thanks that explains it. Otherwise you need to write @PrimalZed Essentially it picks the first matching overload yes. |
closed via #2523. |
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
RxJS version: 5.3.0
Code to reproduce:
Expected behavior: Can take an input type T[] and return type T[] without specifying typing.
Actual behavior: On input type T[], defaults return type T[][].
Additional information:
This was introduced with the fix to #2382
My current workaround is to simply specify the types, e.g.
.reduce<number[], number[]>(...)
The text was updated successfully, but these errors were encountered: