-
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
feat(rx): A new method of piping has been added #7229
Changes from all commits
4da2e83
5b196ef
17c0d6c
de44750
6d0519a
8d92cad
72f9b47
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { rx, map, of, toArray, filter } from 'rxjs'; | ||
import { A, B, C, D, E, F, G, H, I, J } from '../helpers' | ||
|
||
it('should infer conversions from ObservableInputs', () => { | ||
const o1 = rx([1, 2, 3]); // $ExpectType Observable<number> | ||
const o2 = rx(new Set<number>()); // $ExpectType Observable<number> | ||
const o3 = rx(new Map<string, number>()); // $ExpectType Observable<[string, number]> | ||
const o4 = rx(of(1, 2, 3)); // $ExpectType Observable<number> | ||
const o5 = rx(Promise.resolve(1)); // $ExpectType Observable<number> | ||
const o6 = rx(Promise.resolve([1, 2, 3])); // $ExpectType Observable<number[]> | ||
|
||
function* test() { | ||
yield 1; | ||
yield 2; | ||
yield 3; | ||
} | ||
|
||
const o7 = rx(test()); // $ExpectType Observable<1 | 2 | 3> | ||
|
||
async function* test2() { | ||
yield 1; | ||
yield 2; | ||
yield 3; | ||
} | ||
|
||
const o8 = rx(test2()); // $ExpectType Observable<1 | 2 | 3> | ||
const o9 = rx({}); // $ExpectError | ||
}); | ||
|
||
it('should compose with pipeable functions, passing an Observable to the first of those functions', () => { | ||
const o1 = rx([1, 2, 3], map(n => n + 1)); // $ExpectType Observable<number> | ||
const o2 = rx([1, 2, 3], map(n => n + 1), filter(n => n < 3)); // $ExpectType Observable<number> | ||
const o3 = rx([1, 2, 3], map(n => n + 1), filter(n => n < 3), toArray()); // $ExpectType Observable<number[]> | ||
const o4 = rx([1, 2, 3], map(n => n + 1), filter(n => n < 3), toArray(), map(n => n.length)); // $ExpectType Observable<number> | ||
|
||
// Even with unary functions that are not RxJS operators | ||
const o5 = rx([1, 2, 3], map(n => n + 1), toArray(), source => Object.keys(source), keys => keys.length); // $ExpectType number | ||
|
||
// Maybe as a means of subscription | ||
const o6 = rx([1, 2, 3], map(n => n + 1), toArray(), source => source.subscribe()); // $ExpectType Subscription | ||
}) | ||
|
||
|
||
it('should handle a large number of unary functions appropriately', () => { | ||
const r0 = rx([1, 2, 3]); // $ExpectType Observable<number> | ||
const r1 = rx([1, 2, 3], () => new A()); // $ExpectType A | ||
const r2 = rx([1, 2, 3], () => new A(), () => new B()); // $ExpectType B | ||
const r3 = rx([1, 2, 3], () => new A(), () => new B(), () => new C()); // $ExpectType C | ||
const r4 = rx([1, 2, 3], () => new A(), () => new B(), () => new C(), () => new D()); // $ExpectType D | ||
const r5 = rx([1, 2, 3], () => new A(), () => new B(), () => new C(), () => new D(), () => new E()); // $ExpectType E | ||
const r6 = rx([1, 2, 3], () => new A(), () => new B(), () => new C(), () => new D(), () => new E(), () => new F()); // $ExpectType F | ||
const r7 = rx([1, 2, 3], () => new A(), () => new B(), () => new C(), () => new D(), () => new E(), () => new F(), () => new G()); // $ExpectType G | ||
const r8 = rx([1, 2, 3], () => new A(), () => new B(), () => new C(), () => new D(), () => new E(), () => new F(), () => new G(), () => new H()); // $ExpectType H | ||
const r9 = rx([1, 2, 3], () => new A(), () => new B(), () => new C(), () => new D(), () => new E(), () => new F(), () => new G(), () => new H(), () => new I()); // $ExpectType unknown | ||
const r10 = rx([1, 2, 3], () => new A(), () => new B(), () => new C(), () => new D(), () => new E(), () => new F(), () => new G(), () => new H(), () => new I(), () => new J()); // $ExpectType unknown | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { expect } from "chai"; | ||
import { map, Observable, rx } from "rxjs"; | ||
|
||
describe('rx', () => { | ||
it('should work like pipe, convert the first argument to an observable', () => { | ||
const a = [1, 2, 3]; | ||
const results: any[] = []; | ||
|
||
rx(a, map(x => x + 1)).subscribe({ | ||
next: value => results.push(value), | ||
complete: () => { | ||
results.push('done'); | ||
} | ||
}) | ||
expect(results).to.deep.equal([2, 3, 4, 'done']) | ||
}); | ||
|
||
it('should simply convert the first argument to an observable if it is the only thing provided', () => { | ||
const a = [1, 2, 3]; | ||
const results: any[] = []; | ||
|
||
rx(a).subscribe({ | ||
next: value => results.push(value), | ||
complete: () => { | ||
results.push('done'); | ||
} | ||
}) | ||
expect(results).to.deep.equal([1, 2, 3, 'done']) | ||
}); | ||
|
||
it('should allow any kind of custom piping', () => { | ||
const a = [1, 2, 3]; | ||
const result = rx(a, map(x => x + 1), source => source instanceof Observable) | ||
expect(result).to.be.true; | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,8 @@ | ||
import { Subscriber } from './Subscriber'; | ||
import { Subscription } from './Subscription'; | ||
import { TeardownLogic, OperatorFunction, Subscribable, Observer } from './types'; | ||
import { TeardownLogic, UnaryFunction, Subscribable, Observer, OperatorFunction } from './types'; | ||
import { observable as Symbol_observable } from './symbol/observable'; | ||
import { pipeFromArray } from './util/pipe'; | ||
|
||
/** | ||
* A representation of any set of values over any amount of time. This is the most basic building block | ||
* of RxJS. | ||
|
@@ -256,72 +255,79 @@ export class Observable<T> implements Subscribable<T> { | |
|
||
/* tslint:disable:max-line-length */ | ||
pipe(): Observable<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>(op1: UnaryFunction<Observable<T>, A>): A; | ||
pipe<A, B>(op1: UnaryFunction<Observable<T>, A>, op2: UnaryFunction<A, B>): B; | ||
pipe<A, B, C>(op1: UnaryFunction<Observable<T>, A>, op2: UnaryFunction<A, B>, op3: UnaryFunction<B, C>): C; | ||
pipe<A, B, C, D>(op1: UnaryFunction<Observable<T>, A>, op2: UnaryFunction<A, B>, op3: UnaryFunction<B, C>, op4: UnaryFunction<C, D>): 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>; | ||
op1: UnaryFunction<Observable<T>, A>, | ||
op2: UnaryFunction<A, B>, | ||
op3: UnaryFunction<B, C>, | ||
op4: UnaryFunction<C, D>, | ||
op5: UnaryFunction<D, E> | ||
): 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>; | ||
op1: UnaryFunction<Observable<T>, A>, | ||
op2: UnaryFunction<A, B>, | ||
op3: UnaryFunction<B, C>, | ||
op4: UnaryFunction<C, D>, | ||
op5: UnaryFunction<D, E>, | ||
op6: UnaryFunction<E, F> | ||
): 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>; | ||
op1: UnaryFunction<Observable<T>, A>, | ||
op2: UnaryFunction<A, B>, | ||
op3: UnaryFunction<B, C>, | ||
op4: UnaryFunction<C, D>, | ||
op5: UnaryFunction<D, E>, | ||
op6: UnaryFunction<E, F>, | ||
op7: UnaryFunction<F, G> | ||
): 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>; | ||
op1: UnaryFunction<Observable<T>, A>, | ||
op2: UnaryFunction<A, B>, | ||
op3: UnaryFunction<B, C>, | ||
op4: UnaryFunction<C, D>, | ||
op5: UnaryFunction<D, E>, | ||
op6: UnaryFunction<E, F>, | ||
op7: UnaryFunction<F, G>, | ||
op8: UnaryFunction<G, H> | ||
): 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>; | ||
op1: UnaryFunction<Observable<T>, A>, | ||
op2: UnaryFunction<A, B>, | ||
op3: UnaryFunction<B, C>, | ||
op4: UnaryFunction<C, D>, | ||
op5: UnaryFunction<D, E>, | ||
op6: UnaryFunction<E, F>, | ||
op7: UnaryFunction<F, G>, | ||
op8: UnaryFunction<G, H>, | ||
op9: UnaryFunction<H, I> | ||
): I; | ||
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>, | ||
op1: UnaryFunction<Observable<T>, A>, | ||
op2: UnaryFunction<A, B>, | ||
op3: UnaryFunction<B, C>, | ||
op4: UnaryFunction<C, D>, | ||
op5: UnaryFunction<D, E>, | ||
op6: UnaryFunction<E, F>, | ||
op7: UnaryFunction<F, G>, | ||
op8: UnaryFunction<G, H>, | ||
op9: UnaryFunction<H, I>, | ||
...operations: OperatorFunction<any, any>[] | ||
): Observable<unknown>; | ||
pipe<A, B, C, D, E, F, G, H, I>( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I really wish we either had a dedicated pipe operator in js or at least had some way to use recursive/conditional types powerful enough to support not needing to do this. |
||
op1: UnaryFunction<Observable<T>, A>, | ||
op2: UnaryFunction<A, B>, | ||
op3: UnaryFunction<B, C>, | ||
op4: UnaryFunction<C, D>, | ||
op5: UnaryFunction<D, E>, | ||
op6: UnaryFunction<E, F>, | ||
op7: UnaryFunction<F, G>, | ||
op8: UnaryFunction<G, H>, | ||
op9: UnaryFunction<H, I>, | ||
...operations: UnaryFunction<any, any>[] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we replace the |
||
): unknown; | ||
/* tslint:enable:max-line-length */ | ||
|
||
/** | ||
|
@@ -344,7 +350,7 @@ export class Observable<T> implements Subscribable<T> { | |
* .subscribe(x => console.log(x)); | ||
* ``` | ||
*/ | ||
pipe(...operations: OperatorFunction<any, any>[]): Observable<any> { | ||
pipe(...operations: UnaryFunction<any, any>[]): unknown { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we replace the |
||
return pipeFromArray(operations)(this); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we replace the
any
usage here withunknown
?