From bdd52f31a61385f7a29b6241a43d8fcf3d11d4c5 Mon Sep 17 00:00:00 2001 From: Ben Lesh Date: Mon, 1 Mar 2021 16:54:17 -0600 Subject: [PATCH] fix(defaultIfEmpty): Allow `undefined` as an argument, require an argument BREAKING CHANGE: `defaultIfEmpty` requires a value be passed. Will no longer convert `undefined` to `null` for no good reason. Resolves #6064 --- api_guard/dist/types/operators/index.d.ts | 5 +++-- spec-dtslint/operators/defaultIfEmpty-spec.ts | 10 ++++++++-- spec/operators/defaultIfEmpty-spec.ts | 19 ++++--------------- src/internal/operators/defaultIfEmpty.ts | 10 +++------- 4 files changed, 18 insertions(+), 26 deletions(-) diff --git a/api_guard/dist/types/operators/index.d.ts b/api_guard/dist/types/operators/index.d.ts index 6fe502923a..886f3b437e 100644 --- a/api_guard/dist/types/operators/index.d.ts +++ b/api_guard/dist/types/operators/index.d.ts @@ -68,7 +68,7 @@ export declare function debounce(durationSelector: (value: T) => ObservableIn export declare function debounceTime(dueTime: number, scheduler?: SchedulerLike): MonoTypeOperatorFunction; -export declare function defaultIfEmpty(defaultValue?: R): OperatorFunction; +export declare function defaultIfEmpty(defaultValue: R): OperatorFunction; export declare function delay(due: number | Date, scheduler?: SchedulerLike): MonoTypeOperatorFunction; @@ -86,7 +86,8 @@ export declare function distinctUntilChanged(comparator: (previous: K, cur export declare function distinctUntilKeyChanged(key: keyof T): MonoTypeOperatorFunction; export declare function distinctUntilKeyChanged(key: K, compare: (x: T[K], y: T[K]) => boolean): MonoTypeOperatorFunction; -export declare function elementAt(index: number, defaultValue?: T): MonoTypeOperatorFunction; +export declare function elementAt(index: number): MonoTypeOperatorFunction; +export declare function elementAt(index: number, defaultValue: D): OperatorFunction; export declare function endWith(scheduler: SchedulerLike): MonoTypeOperatorFunction; export declare function endWith(v1: A, scheduler: SchedulerLike): OperatorFunction; diff --git a/spec-dtslint/operators/defaultIfEmpty-spec.ts b/spec-dtslint/operators/defaultIfEmpty-spec.ts index 84ee0877f0..00be547bfa 100644 --- a/spec-dtslint/operators/defaultIfEmpty-spec.ts +++ b/spec-dtslint/operators/defaultIfEmpty-spec.ts @@ -1,8 +1,9 @@ -import { of } from 'rxjs'; +import { EMPTY, of } from 'rxjs'; import { defaultIfEmpty, map } from 'rxjs/operators'; it('should infer correctly', () => { - const o = of(1, 2, 3).pipe(defaultIfEmpty()); // $ExpectType Observable + const o = of(1, 2, 3).pipe(defaultIfEmpty()); // $ExpectError + const o2 = of(undefined).pipe(defaultIfEmpty(undefined)); // $ExpectType Observable }); it('should infer correctly with a defaultValue', () => { @@ -11,6 +12,7 @@ it('should infer correctly with a defaultValue', () => { it('should infer correctly with a different type of defaultValue', () => { const o = of(1, 2, 3).pipe(defaultIfEmpty('carbonara')); // $ExpectType Observable + const o2 = of(1, 2, 3).pipe(defaultIfEmpty('carbonara')); // $ExpectType Observable }); it('should infer correctly with a subtype passed through parameters', () => { @@ -20,3 +22,7 @@ it('should infer correctly with a subtype passed through parameters', () => { it('should enforce types', () => { const o = of(1, 2, 3).pipe(defaultIfEmpty(4, 5)); // $ExpectError }); + +it('should handle Observable appropriately', () => { + const o = EMPTY.pipe(defaultIfEmpty('blah')); // $ExpectType Observable +}) diff --git a/spec/operators/defaultIfEmpty-spec.ts b/spec/operators/defaultIfEmpty-spec.ts index db501ac07b..efb5d01408 100644 --- a/spec/operators/defaultIfEmpty-spec.ts +++ b/spec/operators/defaultIfEmpty-spec.ts @@ -35,17 +35,6 @@ describe('defaultIfEmpty', () => { }); }); - it('should return null if the Observable is empty and no arguments', () => { - testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => { - const e1 = cold(' |'); - const e1subs = ' (^!)'; - const expected = '(x|)'; - - expectObservable(e1.pipe(defaultIfEmpty())).toBe(expected, { x: null }); - expectSubscriptions(e1.subscriptions).toBe(e1subs); - }); - }); - it('should return the Observable if not empty with a default value', () => { testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => { const e1 = hot(' --a--b--|'); @@ -57,13 +46,13 @@ describe('defaultIfEmpty', () => { }); }); - it('should return the Observable if not empty with no default value', () => { + it('should allow undefined as a default value', () => { testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => { - const e1 = hot(' --a--b--|'); + const e1 = hot(' --------|'); const e1subs = ' ^-------!'; - const expected = '--a--b--|'; + const expected = '--------(U|)'; - expectObservable(e1.pipe(defaultIfEmpty())).toBe(expected); + expectObservable(e1.pipe(defaultIfEmpty(undefined))).toBe(expected, { U: undefined }); expectSubscriptions(e1.subscriptions).toBe(e1subs); }); }); diff --git a/src/internal/operators/defaultIfEmpty.ts b/src/internal/operators/defaultIfEmpty.ts index aaf8887710..ceba8d4962 100644 --- a/src/internal/operators/defaultIfEmpty.ts +++ b/src/internal/operators/defaultIfEmpty.ts @@ -2,10 +2,6 @@ import { OperatorFunction } from '../types'; import { operate } from '../util/lift'; import { OperatorSubscriber } from './OperatorSubscriber'; -/* tslint:disable:max-line-length */ -export function defaultIfEmpty(defaultValue?: R): OperatorFunction; -/* tslint:enable:max-line-length */ - /** * Emits a given value if the source Observable completes without emitting any * `next` value, otherwise mirrors the source Observable. @@ -34,13 +30,13 @@ export function defaultIfEmpty(defaultValue?: R): OperatorFunction(defaultValue: R | null = null): OperatorFunction { +export function defaultIfEmpty(defaultValue: R): OperatorFunction { return operate((source, subscriber) => { let hasValue = false; source.subscribe(