Skip to content

Commit e8adbb5

Browse files
committed
feat(of): Update of typings
- `of()` now properly infers `Observable<never>` - `of()` can handle any number of arguments gracefully BREAKING CHANGE: Generic signature changed, do not specify generics, allow them to be inferred or use `as` BREAKING CHANGE: Use with more than 9 arguments, where the last argument is a `SchedulerLike` may result in the wrong type which includes the `SchedulerLike`, even though the run time implementation does not support that. Developers should be using `scheduled` instead
1 parent 741a136 commit e8adbb5

5 files changed

Lines changed: 93 additions & 34 deletions

File tree

spec-dtslint/observables/of-spec.ts

Lines changed: 69 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { of, animationFrameScheduler } from 'rxjs';
1+
import { of, animationFrameScheduler, queueScheduler } from 'rxjs';
22
import { A, B, C, D, E, F, G, H, I, J } from '../helpers';
33

44
const a = new A();
@@ -12,6 +12,16 @@ const h = new H();
1212
const i = new I();
1313
const j = new J();
1414

15+
it('should infer never with 0 params', () => {
16+
const res = of(); // $ExpectType Observable<never>
17+
});
18+
19+
it('forced generic should not cause an issue', () => {
20+
const x: any = null;
21+
const res = of<string>(); // $ExpectType Observable<string>
22+
const res2 = of<string>(x); // $ExpectType Observable<string>
23+
});
24+
1525
it('should infer correctly with 1 param', () => {
1626
const res = of(new A()); // $ExpectType Observable<A>
1727
});
@@ -52,13 +62,23 @@ it('should infer correcly with mono type of more than 9 params', () => {
5262
const res = of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // $ExpectType Observable<number>
5363
});
5464

55-
/*
56-
TODO: The below test throws error where it should infer correctly with empty interface({})
57-
shoudl be able to comment back in when https://github.com/ReactiveX/rxjs/issues/4502 is resolved
58-
it('should not support mixed type of more than 9 params', () => {
59-
const res = of(a, b, c, d, e, f, g, h, i, j); // $TODO: Shoule ExpectType Observable<{}>
65+
it('should support mixed type of 9 params', () => {
66+
const res = of(a, b, c, d, e, f, g, h, i, j); // $ExpectType Observable<A | B | C | D | E | F | G | H | I | J>
67+
});
68+
69+
it('should support mixed type of 13 params', () => {
70+
const res = of(a, b, c, d, e, f, g, h, i, j, '', true, 123, [1, 2, 3]); // $ExpectType Observable<string | number | boolean | number[] | A | B | C | D | E | F | G | H | I | J>
71+
});
72+
73+
it('should support a rest of params', () => {
74+
const arr = [a, b, c, d, e, f, g, h, i, j];
75+
const res = of(...arr); // $ExpectType Observable<A | B | C | D | E | F | G | H | I | J>
76+
77+
const arr2 = ['test', 123, a];
78+
const res2 = of(...arr2); // $ExpectType Observable<string | number | A>
79+
80+
const res3 = of(b, ...arr2, c, true); // $ExpectType Observable<string | number | boolean | A | B | C>
6081
});
61-
*/
6282

6383
it('should support scheduler', () => {
6484
const res = of(a, animationFrameScheduler); // $ExpectType Observable<A>
@@ -67,3 +87,45 @@ it('should support scheduler', () => {
6787
it('should infer correctly with array', () => {
6888
const res = of([a, b, c]); // $ExpectType Observable<(A | B | C)[]>
6989
});
90+
91+
92+
// SchedulerLike inclusions (remove in v8)
93+
it('should infer never with 0 params', () => {
94+
const res = of(queueScheduler); // $ExpectType Observable<never>
95+
});
96+
97+
it('should infer correctly with 1 param', () => {
98+
const res = of(new A(), queueScheduler); // $ExpectType Observable<A>
99+
});
100+
101+
it('should infer correcly with mixed type of 2 params', () => {
102+
const res = of(a, b, queueScheduler); // $ExpectType Observable<A | B>
103+
});
104+
105+
it('should infer correcly with mixed type of 3 params', () => {
106+
const res = of(a, b, c, queueScheduler); // $ExpectType Observable<A | B | C>
107+
});
108+
109+
it('should infer correcly with mixed type of 4 params', () => {
110+
const res = of(a, b, c, d, queueScheduler); // $ExpectType Observable<A | B | C | D>
111+
});
112+
113+
it('should infer correcly with mixed type of 5 params', () => {
114+
const res = of(a, b, c, d, e, queueScheduler); // $ExpectType Observable<A | B | C | D | E>
115+
});
116+
117+
it('should infer correcly with mixed type of 6 params', () => {
118+
const res = of(a, b, c, d, e, f, queueScheduler); // $ExpectType Observable<A | B | C | D | E | F>
119+
});
120+
121+
it('should infer correcly with mixed type of 7 params', () => {
122+
const res = of(a, b, c, d, e, f, g, queueScheduler); // $ExpectType Observable<A | B | C | D | E | F | G>
123+
});
124+
125+
it('should infer correcly with mixed type of 8 params', () => {
126+
const res = of(a, b, c, d, e, f, g, h, queueScheduler); // $ExpectType Observable<A | B | C | D | E | F | G | H>
127+
});
128+
129+
it('should infer correcly with mixed type of 9 params', () => {
130+
const res = of(a, b, c, d, e, f, g, h, i, queueScheduler); // $ExpectType Observable<A | B | C | D | E | F | G | H | I>
131+
});

spec/observables/combineLatest-spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ describe('static combineLatest', () => {
2121
});
2222

2323
it('should combine an immediately-scheduled source with an immediately-scheduled second', (done) => {
24-
const a = of<number>(1, 2, 3, queueScheduler);
25-
const b = of<number>(4, 5, 6, 7, 8, queueScheduler);
24+
const a = of(1, 2, 3, queueScheduler);
25+
const b = of(4, 5, 6, 7, 8, queueScheduler);
2626
const r = [[1, 4], [2, 4], [2, 5], [3, 5], [3, 6], [3, 7], [3, 8]];
2727

2828
//type definition need to be updated

src/internal/observable/concat.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,5 +139,5 @@ export function concat<R>(...observables: (ObservableInput<any> | SchedulerLike)
139139
* @owner Observable
140140
*/
141141
export function concat<O extends ObservableInput<any>, R>(...observables: Array<O | SchedulerLike>): Observable<ObservedValueOf<O> | R> {
142-
return concatAll<R>()(of(...observables));
142+
return concatAll<R>()(of(...observables) as Observable<ObservedValueOf<O>>);
143143
}

src/internal/observable/of.ts

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,42 @@
1-
import { SchedulerLike } from '../types';
1+
import { SchedulerLike, ArrayValueOf } from '../types';
22
import { isScheduler } from '../util/isScheduler';
33
import { fromArray } from './fromArray';
44
import { Observable } from '../Observable';
55
import { scheduleArray } from '../scheduled/scheduleArray';
6+
import { never } from './never';
67

78
/* tslint:disable:max-line-length */
8-
/** @deprecated use {@link scheduled} instead `scheduled([a, b, c], scheduler)` */
9+
/** @deprecated remove in v8. Use {@link scheduled} instead `scheduled([], scheduler)` */
10+
export function of(scheduler: SchedulerLike): Observable<never>;
11+
/** @deprecated remove in v8. Use {@link scheduled} instead `scheduled([a, b, c], scheduler)` */
912
export function of<T>(a: T, scheduler: SchedulerLike): Observable<T>;
10-
/** @deprecated use {@link scheduled} instead `scheduled([a, b, c], scheduler)` */
13+
/** @deprecated remove in v8. Use {@link scheduled} instead `scheduled([a, b, c], scheduler)` */
1114
export function of<T, T2>(a: T, b: T2, scheduler: SchedulerLike): Observable<T | T2>;
12-
/** @deprecated use {@link scheduled} instead `scheduled([a, b, c], scheduler)` */
15+
/** @deprecated remove in v8. Use {@link scheduled} instead `scheduled([a, b, c], scheduler)` */
1316
export function of<T, T2, T3>(a: T, b: T2, c: T3, scheduler: SchedulerLike): Observable<T | T2 | T3>;
14-
/** @deprecated use {@link scheduled} instead `scheduled([a, b, c], scheduler)` */
17+
/** @deprecated remove in v8. Use {@link scheduled} instead `scheduled([a, b, c], scheduler)` */
1518
export function of<T, T2, T3, T4>(a: T, b: T2, c: T3, d: T4, scheduler: SchedulerLike): Observable<T | T2 | T3 | T4>;
16-
/** @deprecated use {@link scheduled} instead `scheduled([a, b, c], scheduler)` */
19+
/** @deprecated remove in v8. Use {@link scheduled} instead `scheduled([a, b, c], scheduler)` */
1720
export function of<T, T2, T3, T4, T5>(a: T, b: T2, c: T3, d: T4, e: T5, scheduler: SchedulerLike): Observable<T | T2 | T3 | T4 | T5>;
18-
/** @deprecated use {@link scheduled} instead `scheduled([a, b, c], scheduler)` */
21+
/** @deprecated remove in v8. Use {@link scheduled} instead `scheduled([a, b, c], scheduler)` */
1922
export function of<T, T2, T3, T4, T5, T6>(a: T, b: T2, c: T3, d: T4, e: T5, f: T6, scheduler: SchedulerLike): Observable<T | T2 | T3 | T4 | T5 | T6>;
20-
/** @deprecated use {@link scheduled} instead `scheduled([a, b, c], scheduler)` */
23+
/** @deprecated remove in v8. Use {@link scheduled} instead `scheduled([a, b, c], scheduler)` */
2124
export function of<T, T2, T3, T4, T5, T6, T7>(a: T, b: T2, c: T3, d: T4, e: T5, f: T6, g: T7, scheduler: SchedulerLike):
2225
Observable<T | T2 | T3 | T4 | T5 | T6 | T7>;
23-
/** @deprecated use {@link scheduled} instead `scheduled([a, b, c], scheduler)` */
26+
/** @deprecated remove in v8. Use {@link scheduled} instead `scheduled([a, b, c], scheduler)` */
2427
export function of<T, T2, T3, T4, T5, T6, T7, T8>(a: T, b: T2, c: T3, d: T4, e: T5, f: T6, g: T7, h: T8, scheduler: SchedulerLike):
2528
Observable<T | T2 | T3 | T4 | T5 | T6 | T7 | T8>;
26-
/** @deprecated use {@link scheduled} instead `scheduled([a, b, c], scheduler)` */
29+
/** @deprecated remove in v8. Use {@link scheduled} instead `scheduled([a, b, c], scheduler)` */
2730
export function of<T, T2, T3, T4, T5, T6, T7, T8, T9>(a: T, b: T2, c: T3, d: T4, e: T5, f: T6, g: T7, h: T8, i: T9, scheduler: SchedulerLike):
2831
Observable<T | T2 | T3 | T4 | T5 | T6 | T7 | T8 | T9>;
29-
export function of<T>(...args: (T | SchedulerLike)[]): Observable<T>;
3032

3133
// TODO(benlesh): Update the typings for this when we can switch to TS 3.x
32-
export function of<T>(a: T): Observable<T>;
33-
export function of<T, T2>(a: T, b: T2): Observable<T | T2>;
34-
export function of<T, T2, T3>(a: T, b: T2, c: T3): Observable<T | T2 | T3>;
35-
export function of<T, T2, T3, T4>(a: T, b: T2, c: T3, d: T4): Observable<T | T2 | T3 | T4>;
36-
export function of<T, T2, T3, T4, T5>(a: T, b: T2, c: T3, d: T4, e: T5): Observable<T | T2 | T3 | T4 | T5>;
37-
export function of<T, T2, T3, T4, T5, T6>(a: T, b: T2, c: T3, d: T4, e: T5, f: T6): Observable<T | T2 | T3 | T4 | T5 | T6>;
38-
export function of<T, T2, T3, T4, T5, T6, T7>(a: T, b: T2, c: T3, d: T4, e: T5, f: T6, g: T7):
39-
Observable<T | T2 | T3 | T4 | T5 | T6 | T7>;
40-
export function of<T, T2, T3, T4, T5, T6, T7, T8>(a: T, b: T2, c: T3, d: T4, e: T5, f: T6, g: T7, h: T8):
41-
Observable<T | T2 | T3 | T4 | T5 | T6 | T7 | T8>;
42-
export function of<T, T2, T3, T4, T5, T6, T7, T8, T9>(a: T, b: T2, c: T3, d: T4, e: T5, f: T6, g: T7, h: T8, i: T9):
43-
Observable<T | T2 | T3 | T4 | T5 | T6 | T7 | T8 | T9>;
44-
export function of<T>(...args: T[]): Observable<T>;
34+
export function of(): Observable<never>;
35+
/** @deprecated remove in v8. Do not use generic arguments directly, allow inference or cast with `as` */
36+
export function of<T>(): Observable<T>;
37+
/** @deprecated remove in v8. Do not use generic arguments directly, allow inference or cast with `as` */
38+
export function of<T>(value: T): Observable<T>;
39+
export function of<A extends Array<any>>(...args: A): Observable<ArrayValueOf<A>>;
4540
/* tslint:enable:max-line-length */
4641

4742
/**

src/internal/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,5 @@ export interface SchedulerAction<T> extends Subscription {
101101
export type ObservedValueOf<O> = O extends ObservableInput<infer T> ? T : never;
102102

103103
export type ObservedValuesFromArray<X> = X extends Array<ObservableInput<infer T>> ? T : never;
104+
105+
export type ArrayValueOf<A> = A extends Array<infer T> ? T : never;

0 commit comments

Comments
 (0)