From 40c3d9f824204cf8c9afe3d11a5036b0be48674d Mon Sep 17 00:00:00 2001 From: Ben Lesh Date: Mon, 14 Jan 2019 17:46:56 -0800 Subject: [PATCH] fix(combineLatest): improve typings for combineLatest (#4470) * fix(combineLatest): improve typings for combineLatest Existing typings did a poor job of getting proper types from code that passed an array of observables or observable inputs to combineLatest. This issue was caught while trying master in google3. This resolves that issue. * fixup! fix(combineLatest): improve typings for combineLatest --- .../observables/combineLatest-spec.ts | 60 +++++++++++++++++++ spec-dtslint/observables/from-spec.ts | 2 +- src/internal/observable/combineLatest.ts | 32 ++++++++-- 3 files changed, 89 insertions(+), 5 deletions(-) diff --git a/spec-dtslint/observables/combineLatest-spec.ts b/spec-dtslint/observables/combineLatest-spec.ts index 62b070dce7..6ffc80e310 100644 --- a/spec-dtslint/observables/combineLatest-spec.ts +++ b/spec-dtslint/observables/combineLatest-spec.ts @@ -77,3 +77,63 @@ it('should accept 6 params and a result selector', () => { it('should accept 7 or more params and a result selector', () => { const o = combineLatest(a, b, c, d, e, f, g, g, g, () => new A()); // $ExpectType Observable }); + +it('should accept 1 param', () => { + const o = combineLatest([a]); // $ExpectType Observable<[A]> +}); + +it('should accept 2 params', () => { + const o = combineLatest([a, b]); // $ExpectType Observable<[A, B]> +}); + +it('should accept 3 params', () => { + const o = combineLatest([a, b, c]); // $ExpectType Observable<[A, B, C]> +}); + +it('should accept 4 params', () => { + const o = combineLatest([a, b, c, d]); // $ExpectType Observable<[A, B, C, D]> +}); + +it('should accept 5 params', () => { + const o = combineLatest([a, b, c, d, e]); // $ExpectType Observable<[A, B, C, D, E]> +}); + +it('should accept 6 params', () => { + const o = combineLatest([a, b, c, d, e, f]); // $ExpectType Observable<[A, B, C, D, E, F]> +}); + +it('should have basic support for 7 or more params', () => { + const o = combineLatest([a, b, c, d, e, f, g]); // $ExpectType Observable<(A | B | C | D | E | F | G)[]> +}); + +it('should handle an array of Observables', () => { + const o = combineLatest([a, a, a, a, a, a, a, a, a, a, a]); // $ExpectType Observable +}); + +it('should accept 1 param and a result selector', () => { + const o = combineLatest([a], (a: A) => new A()); // $ExpectType Observable +}); + +it('should accept 2 params and a result selector', () => { + const o = combineLatest([a, b], (a: A, b: B) => new A()); // $ExpectType Observable +}); + +it('should accept 3 params and a result selector', () => { + const o = combineLatest([a, b, c], (a: A, b: B, c: C) => new A()); // $ExpectType Observable +}); + +it('should accept 4 params and a result selector', () => { + const o = combineLatest([a, b, c, d], (a: A, b: B, c: C, d: D) => new A()); // $ExpectType Observable +}); + +it('should accept 5 params and a result selector', () => { + const o = combineLatest([a, b, c, d, e], (a: A, b: B, c: C, d: D, e: E) => new A()); // $ExpectType Observable +}); + +it('should accept 6 params and a result selector', () => { + const o = combineLatest([a, b, c, d, e, f], (a: A, b: B, c: C, d: D, e: E, f: F) => new A()); // $ExpectType Observable +}); + +it('should accept 7 or more params and a result selector', () => { + const o = combineLatest([a, b, c, d, e, f, g, g, g], (a: any, b: any, c: any, d: any, e: any, f: any, g1: any, g2: any, g3: any) => new A()); // $ExpectType Observable +}); diff --git a/spec-dtslint/observables/from-spec.ts b/spec-dtslint/observables/from-spec.ts index ec0cb7fb62..103626c710 100644 --- a/spec-dtslint/observables/from-spec.ts +++ b/spec-dtslint/observables/from-spec.ts @@ -41,5 +41,5 @@ it('should accept an array of Inputs', () => { yield 42; }()); - const o = from([of(1), ['test'], iterable]); // $ExpectType Observable | IterableIterator | string[]> + const o = from([of(1), ['test'], iterable]); // $ExpectType Observable | Observable | string[]> }); diff --git a/src/internal/observable/combineLatest.ts b/src/internal/observable/combineLatest.ts index 984d8f91ba..0b98b6bd68 100644 --- a/src/internal/observable/combineLatest.ts +++ b/src/internal/observable/combineLatest.ts @@ -12,6 +12,24 @@ import { fromArray } from './fromArray'; const NONE = {}; /* tslint:disable:max-line-length */ + +// If called with a single array, it "auto-spreads" the array, with result selector +/** @deprecated resultSelector no longer supported, pipe to map instead */ +export function combineLatest, R>(sources: [O1], resultSelector: (v1: ObservedValueOf) => R, scheduler?: SchedulerLike): Observable; +/** @deprecated resultSelector no longer supported, pipe to map instead */ +export function combineLatest, O2 extends ObservableInput, R>(sources: [O1, O2], resultSelector: (v1: ObservedValueOf, v2: ObservedValueOf) => R, scheduler?: SchedulerLike): Observable; +/** @deprecated resultSelector no longer supported, pipe to map instead */ +export function combineLatest, O2 extends ObservableInput, O3 extends ObservableInput, R>(sources: [O1, O2, O3], resultSelector: (v1: ObservedValueOf, v2: ObservedValueOf, v3: ObservedValueOf) => R, scheduler?: SchedulerLike): Observable; +/** @deprecated resultSelector no longer supported, pipe to map instead */ +export function combineLatest, O2 extends ObservableInput, O3 extends ObservableInput, O4 extends ObservableInput, R>(sources: [O1, O2, O3, O4], resultSelector: (v1: ObservedValueOf, v2: ObservedValueOf, v3: ObservedValueOf, v4: ObservedValueOf) => R, scheduler?: SchedulerLike): Observable; +/** @deprecated resultSelector no longer supported, pipe to map instead */ +export function combineLatest, O2 extends ObservableInput, O3 extends ObservableInput, O4 extends ObservableInput, O5 extends ObservableInput, R>(sources: [O1, O2, O3, O4, O5], resultSelector: (v1: ObservedValueOf, v2: ObservedValueOf, v3: ObservedValueOf, v4: ObservedValueOf, v5: ObservedValueOf) => R, scheduler?: SchedulerLike): Observable; +/** @deprecated resultSelector no longer supported, pipe to map instead */ +export function combineLatest, O2 extends ObservableInput, O3 extends ObservableInput, O4 extends ObservableInput, O5 extends ObservableInput, O6 extends ObservableInput, R>(sources: [O1, O2, O3, O4, O5, O6], resultSelector: (v1: ObservedValueOf, v2: ObservedValueOf, v3: ObservedValueOf, v4: ObservedValueOf, v5: ObservedValueOf, v6: ObservedValueOf) => R, scheduler?: SchedulerLike): Observable; +/** @deprecated resultSelector no longer supported, pipe to map instead */ +export function combineLatest, R>(sources: O[], resultSelector: (...args: ObservedValueOf[]) => R, scheduler?: SchedulerLike): Observable; + +// standard call, but with a result selector /** @deprecated resultSelector no longer supported, pipe to map instead */ export function combineLatest, R>(v1: O1, resultSelector: (v1: ObservedValueOf) => R, scheduler?: SchedulerLike): Observable; /** @deprecated resultSelector no longer supported, pipe to map instead */ @@ -25,6 +43,16 @@ export function combineLatest, O2 extends Observ /** @deprecated resultSelector no longer supported, pipe to map instead */ export function combineLatest, O2 extends ObservableInput, O3 extends ObservableInput, O4 extends ObservableInput, O5 extends ObservableInput, O6 extends ObservableInput, R>(v1: O1, v2: O2, v3: O3, v4: O4, v5: O5, v6: O6, resultSelector: (v1: ObservedValueOf, v2: ObservedValueOf, v3: ObservedValueOf, v4: ObservedValueOf, v5: ObservedValueOf, v6: ObservedValueOf) => R, scheduler?: SchedulerLike): Observable; +// If called with a single array, it "auto-spreads" the array. +export function combineLatest>(sources: [O1], scheduler?: SchedulerLike): Observable<[ObservedValueOf]>; +export function combineLatest, O2 extends ObservableInput>(sources: [O1, O2], scheduler?: SchedulerLike): Observable<[ObservedValueOf, ObservedValueOf]>; +export function combineLatest, O2 extends ObservableInput, O3 extends ObservableInput>(sources: [O1, O2, O3], scheduler?: SchedulerLike): Observable<[ObservedValueOf, ObservedValueOf, ObservedValueOf]>; +export function combineLatest, O2 extends ObservableInput, O3 extends ObservableInput, O4 extends ObservableInput>(sources: [O1, O2, O3, O4], scheduler?: SchedulerLike): Observable<[ObservedValueOf, ObservedValueOf, ObservedValueOf, ObservedValueOf]>; +export function combineLatest, O2 extends ObservableInput, O3 extends ObservableInput, O4 extends ObservableInput, O5 extends ObservableInput>(sources: [O1, O2, O3, O4, O5], scheduler?: SchedulerLike): Observable<[ObservedValueOf, ObservedValueOf, ObservedValueOf, ObservedValueOf, ObservedValueOf]>; +export function combineLatest, O2 extends ObservableInput, O3 extends ObservableInput, O4 extends ObservableInput, O5 extends ObservableInput, O6 extends ObservableInput>(sources: [O1, O2, O3, O4, O5, O6], scheduler?: SchedulerLike): Observable<[ObservedValueOf, ObservedValueOf, ObservedValueOf, ObservedValueOf, ObservedValueOf, ObservedValueOf]>; +export function combineLatest>(sources: O[], scheduler?: SchedulerLike): Observable[]>; + +// Standard calls export function combineLatest>(v1: O1, scheduler?: SchedulerLike): Observable<[ObservedValueOf]>; export function combineLatest, O2 extends ObservableInput>(v1: O1, v2: O2, scheduler?: SchedulerLike): Observable<[ObservedValueOf, ObservedValueOf]>; export function combineLatest, O2 extends ObservableInput, O3 extends ObservableInput>(v1: O1, v2: O2, v3: O3, scheduler?: SchedulerLike): Observable<[ObservedValueOf, ObservedValueOf, ObservedValueOf]>; @@ -32,12 +60,8 @@ export function combineLatest, O2 extends Observ export function combineLatest, O2 extends ObservableInput, O3 extends ObservableInput, O4 extends ObservableInput, O5 extends ObservableInput>(v1: O1, v2: O2, v3: O3, v4: O4, v5: O5, scheduler?: SchedulerLike): Observable<[ObservedValueOf, ObservedValueOf, ObservedValueOf, ObservedValueOf, ObservedValueOf]>; export function combineLatest, O2 extends ObservableInput, O3 extends ObservableInput, O4 extends ObservableInput, O5 extends ObservableInput, O6 extends ObservableInput>(v1: O1, v2: O2, v3: O3, v4: O4, v5: O5, v6: O6, scheduler?: SchedulerLike): Observable<[ObservedValueOf, ObservedValueOf, ObservedValueOf, ObservedValueOf, ObservedValueOf, ObservedValueOf]>; -export function combineLatest>(array: O[], scheduler?: SchedulerLike): Observable[]>; -export function combineLatest(array: ObservableInput[], scheduler?: SchedulerLike): Observable; /** @deprecated resultSelector no longer supported, pipe to map instead */ export function combineLatest, R>(array: O[], resultSelector: (...values: ObservedValueOf[]) => R, scheduler?: SchedulerLike): Observable; -/** @deprecated resultSelector no longer supported, pipe to map instead */ -export function combineLatest(array: ObservableInput[], resultSelector: (...values: Array) => R, scheduler?: SchedulerLike): Observable; export function combineLatest>(...observables: Array): Observable; export function combineLatest, R>(...observables: Array[]) => R) | SchedulerLike>): Observable; export function combineLatest(...observables: Array | ((...values: Array) => R) | SchedulerLike>): Observable;