Skip to content

Commit 6d901cb

Browse files
authored
fix: support N args in static race and ensure observable returned (ReactiveX#5286)
* test: add failing test for race * fix: use from on ObservableInput * fix: support N args for static race * chore: use dtslint helpers
1 parent ab6e9fc commit 6d901cb

File tree

3 files changed

+32
-129
lines changed

3 files changed

+32
-129
lines changed

spec-dtslint/observables/race-spec.ts

+17-105
Original file line numberDiff line numberDiff line change
@@ -1,120 +1,32 @@
11
import { race, of } from 'rxjs';
2-
3-
it('should infer correctly with 1 parameter', () => {
4-
const a = of(1);
5-
const o = race(a); // $ExpectType Observable<number>
6-
});
2+
import { a$, b, b$, c, c$, d$, e$, f$ } from '../helpers';
73

84
describe('race(a, b, c)', () => {
9-
it('should infer correctly with multiple parameters of the same type', () => {
10-
const a = of(1);
11-
const b = of(2);
12-
const o = race(a, b); // $ExpectType Observable<number>
13-
});
14-
15-
it('should support 2 parameters with different types', () => {
16-
const a = of(1);
17-
const b = of('a');
18-
const o = race(a, b); // $ExpectType Observable<string | number>
19-
});
20-
21-
it('should support 3 parameters with different types', () => {
22-
const a = of(1);
23-
const b = of('a');
24-
const c = of(true);
25-
const o = race(a, b, c); // $ExpectType Observable<string | number | boolean>
26-
});
27-
28-
it('should support 4 parameters with different types', () => {
29-
const a = of(1);
30-
const b = of('a');
31-
const c = of(true);
32-
const d = of([1, 2, 3]);
33-
const o = race(a, b, c, d); // $ExpectType Observable<string | number | boolean | number[]>
34-
});
35-
36-
it('should support 5 parameters with different types', () => {
37-
const a = of(1);
38-
const b = of('a');
39-
const c = of(true);
40-
const d = of([1, 2, 3]);
41-
const e = of(['blah']);
42-
const o = race(a, b, c, d, e); // $ExpectType Observable<string | number | boolean | number[] | string[]>
43-
});
44-
45-
it('should support 6 or more parameters of the same type', () => {
46-
const a = of(1);
47-
const o = race(a, a, a, a, a, a, a, a, a, a, a, a, a, a); // $ExpectType Observable<number>
48-
});
49-
50-
it('should return unknown for 6 or more arguments of different types', () => {
51-
const a = of(1);
52-
const b = of('a');
53-
const c = of(true);
54-
const d = of([1, 2, 3]);
55-
const e = of(['blah']);
56-
const f = of({ foo: 'bar' });
57-
const o = race(a, b, c, d, e, f); // $ExpectType Observable<unknown>
5+
it('should support N arguments of different types', () => {
6+
const o1 = race(a$); // $ExpectType Observable<A>
7+
const o2 = race(a$, b$); // $ExpectType Observable<A | B>
8+
const o3 = race(a$, b$, c$); // $ExpectType Observable<A | B | C>
9+
const o4 = race(a$, b$, c$, d$); // $ExpectType Observable<A | B | C | D>
10+
const o5 = race(a$, b$, c$, d$, e$); // $ExpectType Observable<A | B | C | D | E>
11+
const o6 = race(a$, b$, c$, d$, e$, f$); // $ExpectType Observable<A | B | C | D | E | F>
5812
});
5913
});
6014

6115
describe('race([a, b, c])', () => {
62-
it('should infer correctly with multiple parameters of the same type', () => {
63-
const a = of(1);
64-
const b = of(2);
65-
const o = race([a, b]); // $ExpectType Observable<number>
66-
});
67-
68-
it('should support 2 parameters with different types', () => {
69-
const a = of(1);
70-
const b = of('a');
71-
const o = race([a, b]); // $ExpectType Observable<string | number>
72-
});
73-
74-
it('should support 3 parameters with different types', () => {
75-
const a = of(1);
76-
const b = of('a');
77-
const c = of(true);
78-
const o = race([a, b, c]); // $ExpectType Observable<string | number | boolean>
79-
});
80-
81-
it('should support 4 parameters with different types', () => {
82-
const a = of(1);
83-
const b = of('a');
84-
const c = of(true);
85-
const d = of([1, 2, 3]);
86-
const o = race([a, b, c, d]); // $ExpectType Observable<string | number | boolean | number[]>
87-
});
88-
89-
it('should support 5 parameters with different types', () => {
90-
const a = of(1);
91-
const b = of('a');
92-
const c = of(true);
93-
const d = of([1, 2, 3]);
94-
const e = of(['blah']);
95-
const o = race([a, b, c, d, e]); // $ExpectType Observable<string | number | boolean | number[] | string[]>
96-
});
97-
98-
it('should support 6 or more parameters of the same type', () => {
99-
const a = of(1);
100-
const o = race([a, a, a, a, a, a, a, a, a, a, a, a, a, a]); // $ExpectType Observable<number>
101-
});
102-
103-
it('should return {} for 6 or more arguments of different types', () => {
104-
const a = of(1);
105-
const b = of('a');
106-
const c = of(true);
107-
const d = of([1, 2, 3]);
108-
const e = of(['blah']);
109-
const f = of({ foo: 'bar' });
110-
const o = race([a, b, c, d, e, f]); // $ExpectType Observable<unknown>
16+
it('should support N arguments of different types', () => {
17+
const o1 = race([a$]); // $ExpectType Observable<A>
18+
const o2 = race([a$, b$]); // $ExpectType Observable<A | B>
19+
const o3 = race([a$, b$, c$]); // $ExpectType Observable<A | B | C>
20+
const o4 = race([a$, b$, c$, d$]); // $ExpectType Observable<A | B | C | D>
21+
const o5 = race([a$, b$, c$, d$, e$]); // $ExpectType Observable<A | B | C | D | E>
22+
const o6 = race([a$, b$, c$, d$, e$, f$]); // $ExpectType Observable<A | B | C | D | E | F>
11123
});
11224
});
11325

11426
it('should race observable inputs', () => {
115-
const o = race(of(1), Promise.resolve('foo'), [true, false]); // $ExpectType Observable<string | number | boolean>
27+
const o = race(a$, Promise.resolve(b), [c]); // $ExpectType Observable<A | B | C>
11628
});
11729

11830
it('should race an array observable inputs', () => {
119-
const o = race([of(1), Promise.resolve('foo'), [true, false]]); // $ExpectType Observable<string | number | boolean>
31+
const o = race([a$, Promise.resolve(b), [c]]); // $ExpectType Observable<A | B | C>
12032
});

spec/observables/race-spec.ts

+8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { hot, cold, expectObservable, expectSubscriptions } from '../helpers/marble-testing';
22
import { race, of } from 'rxjs';
33
import { mergeMap } from 'rxjs/operators';
4+
import { expect } from 'chai';
45

56
/** @test {race} */
67
describe('static race', () => {
@@ -204,4 +205,11 @@ describe('static race', () => {
204205
expectObservable(source).toBe(expected);
205206
expectSubscriptions(e1.subscriptions).toBe(e1subs);
206207
});
208+
209+
it('should support a single ObservableInput argument', (done: MochaDone) => {
210+
const source = race(Promise.resolve(42));
211+
source.subscribe(value => {
212+
expect(value).to.equal(42);
213+
}, done, done);
214+
});
207215
});

src/internal/observable/race.ts

+7-24
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,17 @@
11
import { Observable } from '../Observable';
22
import { isArray } from '../util/isArray';
3+
import { from } from './from';
34
import { fromArray } from './fromArray';
45
import { Operator } from '../Operator';
56
import { Subscriber } from '../Subscriber';
67
import { Subscription } from '../Subscription';
7-
import { TeardownLogic, ObservableInput } from '../types';
8+
import { TeardownLogic, ObservableInput, ObservedValueUnionFromArray } from '../types';
89
import { OuterSubscriber } from '../OuterSubscriber';
910
import { InnerSubscriber } from '../InnerSubscriber';
1011
import { subscribeToResult } from '../util/subscribeToResult';
1112

12-
// tslint:disable:max-line-length
13-
export function race<A>(arg: [ObservableInput<A>]): Observable<A>;
14-
export function race<A, B>(arg: [ObservableInput<A>, ObservableInput<B>]): Observable<A | B>;
15-
export function race<A, B, C>(arg: [ObservableInput<A>, ObservableInput<B>, ObservableInput<C>]): Observable<A | B | C>;
16-
export function race<A, B, C, D>(arg: [ObservableInput<A>, ObservableInput<B>, ObservableInput<C>, ObservableInput<D>]): Observable<A | B | C | D>;
17-
export function race<A, B, C, D, E>(arg: [ObservableInput<A>, ObservableInput<B>, ObservableInput<C>, ObservableInput<D>, ObservableInput<E>]): Observable<A | B | C | D | E>;
18-
export function race<T>(arg: ObservableInput<T>[]): Observable<T>;
19-
export function race(arg: ObservableInput<any>[]): Observable<unknown>;
20-
21-
export function race<A>(a: ObservableInput<A>): Observable<A>;
22-
export function race<A, B>(a: ObservableInput<A>, b: ObservableInput<B>): Observable<A | B>;
23-
export function race<A, B, C>(a: ObservableInput<A>, b: ObservableInput<B>, c: ObservableInput<C>): Observable<A | B | C>;
24-
export function race<A, B, C, D>(a: ObservableInput<A>, b: ObservableInput<B>, c: ObservableInput<C>, d: ObservableInput<D>): Observable<A | B | C | D>;
25-
export function race<A, B, C, D, E>(a: ObservableInput<A>, b: ObservableInput<B>, c: ObservableInput<C>, d: ObservableInput<D>, e: ObservableInput<E>): Observable<A | B | C | D | E>;
26-
// tslint:enable:max-line-length
27-
28-
export function race<T>(observables: ObservableInput<T>[]): Observable<T>;
29-
export function race(observables: ObservableInput<any>[]): Observable<unknown>;
30-
export function race<T>(...observables: ObservableInput<T>[]): Observable<T>;
31-
export function race(...observables: ObservableInput<any>[]): Observable<unknown>;
13+
export function race<A extends ObservableInput<any>[]>(observables: A): Observable<ObservedValueUnionFromArray<A>>;
14+
export function race<A extends ObservableInput<any>[]>(...observables: A): Observable<ObservedValueUnionFromArray<A>>;
3215

3316
/**
3417
* Returns an observable that mirrors the first source observable to emit an item.
@@ -71,14 +54,14 @@ export function race(...observables: ObservableInput<any>[]): Observable<unknown
7154
* @param {...Observables} ...observables sources used to race for which Observable emits first.
7255
* @return {Observable} an Observable that mirrors the output of the first Observable to emit an item.
7356
*/
74-
export function race<T>(...observables: ObservableInput<any>[]): Observable<T> {
57+
export function race<T>(...observables: (ObservableInput<T> | ObservableInput<T>[])[]): Observable<any> {
7558
// if the only argument is an array, it was most likely called with
7659
// `race([obs1, obs2, ...])`
7760
if (observables.length === 1) {
7861
if (isArray(observables[0])) {
79-
observables = observables[0] as Observable<any>[];
62+
observables = observables[0] as ObservableInput<T>[];
8063
} else {
81-
return observables[0] as Observable<T>;
64+
return from(observables[0] as ObservableInput<T>);
8265
}
8366
}
8467

0 commit comments

Comments
 (0)