diff --git a/spec-dtslint/operators/switchScan-spec.ts b/spec-dtslint/operators/switchScan-spec.ts index 86196c1bfb2..41e03a703e3 100644 --- a/spec-dtslint/operators/switchScan-spec.ts +++ b/spec-dtslint/operators/switchScan-spec.ts @@ -9,16 +9,20 @@ it('should infer correctly when using a single type', () => { const o = of(1, 2, 3).pipe(switchScan((acc, v) => of(acc + v), 0)); // $ExpectType Observable }); -it('should infer correctly when using a seed', () => { - const o = of(1, 2, 3).pipe(switchScan((acc, v) => of(acc + v), 0)); // $ExpectType Observable -}); - it('should infer correctly when using seed of a different type', () => { - const o = of(1, 2, 3).pipe(switchScan((acc: string, v: number) => of(acc + v), '0')); // $ExpectType Observable + const o = of(1, 2, 3).pipe(switchScan((acc, v) => of(acc + v), '0')); // $ExpectType Observable }); it('should support a projector that takes an index', () => { - const o = of(1, 2, 3).pipe(switchScan((acc: boolean, v: number, index: number) => of(Boolean(v)), false)); // $ExpectType Observable + const o = of(1, 2, 3).pipe(switchScan((acc, v, index) => of(Boolean(v)), false)); // $ExpectType Observable +}); + +it('should support projecting to union types', () => { + const o = of(Math.random()).pipe(switchScan(n => n > 0.5 ? of(123) : of('test'), 0)); // $ExpectType Observable +}); + +it('should use the inferred accumulator return type over the seed type', () => { + const o = of(1, 2, 3).pipe(switchScan(p => of(1), [])); // $ExpectType Observable }); it('should enforce types', () => { @@ -29,10 +33,6 @@ it('should enforce the return type to be Observable', () => { const o = of(1, 2, 3).pipe(switchScan(p => p)); // $ExpectError }); -it('should enforce seed and the return type from accumulator', () => { - const o = of(1, 2, 3).pipe(switchScan(p => of(1), [])); // $ExpectError -}); - it('should enforce seed and accumulator to have the same type', () => { const o = of(1, 2, 3).pipe(switchScan((acc, p) => of([...acc, p]))); // $ExpectError }); diff --git a/spec/operators/switchScan-spec.ts b/spec/operators/switchScan-spec.ts index 83422906011..ee3ddaa29e3 100644 --- a/spec/operators/switchScan-spec.ts +++ b/spec/operators/switchScan-spec.ts @@ -8,14 +8,14 @@ declare function asDiagram(arg: string): Function; /** @test {switchScan} */ describe('switchScan', () => { asDiagram('switchScan(i => 10*i\u2014\u201410*i\u2014\u201410*i\u2014|, 0)') - ('should map-and-flatten each item to an Observable while passing the seed', () => { + ('should map-and-flatten each item to an Observable while passing the accumulated value', () => { const e1 = hot('--1-----3--5-------|'); const e1subs = '^ !'; const e2 = cold('x-x-x| ', {x: 10}); const expected = '--x-x-x-y-yz-z-z---|'; const values = {x: 10, y: 40, z: 90}; - const result = e1.pipe(switchScan((acc: number, x: string) => e2.pipe(map(i => i * Number(x) + acc)), 0)); + const result = e1.pipe(switchScan((acc, x) => e2.pipe(map(i => i * Number(x) + acc)), 0)); expectObservable(result).toBe(expected, values); expectSubscriptions(e1.subscriptions).toBe(e1subs); @@ -61,7 +61,7 @@ describe('switchScan', () => { const e1subs = '^ ! '; const expected = '-----------a--b--c----f---g---h---i--|'; - const observableLookup = { x: x, y: y }; + const observableLookup = { x, y }; const result = e1.pipe(switchScan((acc, value) => observableLookup[value], null)); diff --git a/src/internal/operators/switchScan.ts b/src/internal/operators/switchScan.ts index 9d4215cecf1..0683d46ecfb 100644 --- a/src/internal/operators/switchScan.ts +++ b/src/internal/operators/switchScan.ts @@ -1,5 +1,5 @@ import { Observable } from '../Observable'; -import { ObservableInput, OperatorFunction } from '../types'; +import { ObservableInput, ObservedValueOf, OperatorFunction } from '../types'; import { Operator } from '../Operator'; import { Subscriber } from '../Subscriber'; import { switchMap } from './switchMap'; @@ -25,21 +25,21 @@ import { tap } from './tap'; * @method switchScan * @owner Observable */ -export function switchScan( - accumulator: (acc: R, value: T, index: number) => ObservableInput, +export function switchScan>( + accumulator: (acc: R, value: T, index: number) => O, seed: R -): OperatorFunction { +): OperatorFunction> { return (source: Observable) => source.lift(new SwitchScanOperator(accumulator, seed)); } -class SwitchScanOperator implements Operator { - constructor(private accumulator: (acc: R, value: T, index: number) => ObservableInput, private seed: R) { } +class SwitchScanOperator> implements Operator { + constructor(private accumulator: (acc: R, value: T, index: number) => ObservableInput, private seed: R) { } - call(subscriber: Subscriber, source: any): any { + call(subscriber: Subscriber, source: any): any { let seed: R = this.seed; return source.pipe( - switchMap((value: T, index: number): ObservableInput => this.accumulator(seed, value, index)), + switchMap((value: T, index: number) => this.accumulator(seed, value, index)), tap((value: R) => seed = value), ).subscribe(subscriber); }