Skip to content

Commit

Permalink
fix(types): support union type returns in switchMap
Browse files Browse the repository at this point in the history
  • Loading branch information
benlesh committed Jan 9, 2019
1 parent c2ac39c commit 32d35fd
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 11 deletions.
10 changes: 7 additions & 3 deletions spec-dtslint/operators/switchMap-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ it('should infer correctly', () => {
});

it('should support a projector that takes an index', () => {
const o = of(1, 2, 3).pipe(switchMap((p, index) => of(Boolean(p)))); // $ExpectType Observable<boolean>
const o = of(1, 2, 3).pipe(switchMap(p => of(Boolean(p)))); // $ExpectType Observable<boolean>
});

it('should infer correctly by using the resultSelector first parameter', () => {
Expand All @@ -18,11 +18,11 @@ it('should infer correctly by using the resultSelector second parameter', () =>
});

it('should support a resultSelector that takes an inner index', () => {
const o = of(1, 2, 3).pipe(switchMap(p => of(Boolean(p)), (a, b, innnerIndex) => a)); // $ExpectType Observable<number>
const o = of(1, 2, 3).pipe(switchMap(p => of(Boolean(p)), a => a)); // $ExpectType Observable<number>
});

it('should support a resultSelector that takes an inner and outer index', () => {
const o = of(1, 2, 3).pipe(switchMap(p => of(Boolean(p)), (a, b, innnerIndex, outerIndex) => a)); // $ExpectType Observable<number>
const o = of(1, 2, 3).pipe(switchMap(p => of(Boolean(p)), a => a)); // $ExpectType Observable<number>
});

it('should support an undefined resultSelector', () => {
Expand All @@ -36,3 +36,7 @@ it('should enforce types', () => {
it('should enforce the return type', () => {
const o = of(1, 2, 3).pipe(switchMap(p => p)); // $ExpectError
});

it('should support projecting to union types', () => {
const o = of(Math.random()).pipe(switchMap(n => n > 0.5 ? of(123) : of('test'))); // $ExpectType Observable<string | number>
});
16 changes: 8 additions & 8 deletions src/internal/operators/switchMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ import { Subscription } from '../Subscription';
import { OuterSubscriber } from '../OuterSubscriber';
import { InnerSubscriber } from '../InnerSubscriber';
import { subscribeToResult } from '../util/subscribeToResult';
import { ObservableInput, OperatorFunction } from '../types';
import { ObservableInput, OperatorFunction, ObservedValueOf } from '../types';
import { map } from './map';
import { from } from '../observable/from';

/* tslint:disable:max-line-length */
export function switchMap<T, R>(project: (value: T, index: number) => ObservableInput<R>): OperatorFunction<T, R>;
export function switchMap<T, O extends ObservableInput<any>>(project: (value: T, index: number) => O): OperatorFunction<T, ObservedValueOf<O>>;
/** @deprecated resultSelector is no longer supported, use inner map instead */
export function switchMap<T, R>(project: (value: T, index: number) => ObservableInput<R>, resultSelector: undefined): OperatorFunction<T, R>;
export function switchMap<T, O extends ObservableInput<any>>(project: (value: T, index: number) => O, resultSelector: undefined): OperatorFunction<T, ObservedValueOf<O>>;
/** @deprecated resultSelector is no longer supported, use inner map instead */
export function switchMap<T, I, R>(project: (value: T, index: number) => ObservableInput<I>, resultSelector: (outerValue: T, innerValue: I, outerIndex: number, innerIndex: number) => R): OperatorFunction<T, R>;
export function switchMap<T, R, O extends ObservableInput<any>>(project: (value: T, index: number) => O, resultSelector: (outerValue: T, innerValue: ObservedValueOf<O>, outerIndex: number, innerIndex: number) => R): OperatorFunction<T, R>;
/* tslint:enable:max-line-length */

/**
Expand Down Expand Up @@ -59,10 +59,10 @@ export function switchMap<T, I, R>(project: (value: T, index: number) => Observa
* @method switchMap
* @owner Observable
*/
export function switchMap<T, I, R>(
project: (value: T, index: number) => ObservableInput<I>,
resultSelector?: (outerValue: T, innerValue: I, outerIndex: number, innerIndex: number) => R,
): OperatorFunction<T, I|R> {
export function switchMap<T, R, O extends ObservableInput<any>>(
project: (value: T, index: number) => O,
resultSelector?: (outerValue: T, innerValue: ObservedValueOf<O>, outerIndex: number, innerIndex: number) => R,
): OperatorFunction<T, ObservedValueOf<O>|R> {
if (typeof resultSelector === 'function') {
return (source: Observable<T>) => source.pipe(
switchMap((a, i) => from(project(a, i)).pipe(
Expand Down

1 comment on commit 32d35fd

@snebjorn
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This introduces a breaking change if you used the generic types

Before:

   switchMap<string, Foo[]>(...)

After

   switchMap<string, Observable<Foo[]>>(...)

Please sign in to comment.