Skip to content

Commit

Permalink
fix(defaultIfEmpty): Allow undefined as an argument, require an arg…
Browse files Browse the repository at this point in the history
…ument

BREAKING CHANGE: `defaultIfEmpty` requires a value be passed. Will no longer convert `undefined` to `null` for no good reason.

Resolves #6064
  • Loading branch information
benlesh committed Mar 3, 2021
1 parent 1365c41 commit 4983760
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 26 deletions.
5 changes: 3 additions & 2 deletions api_guard/dist/types/operators/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export declare function debounce<T>(durationSelector: (value: T) => ObservableIn

export declare function debounceTime<T>(dueTime: number, scheduler?: SchedulerLike): MonoTypeOperatorFunction<T>;

export declare function defaultIfEmpty<T, R = T>(defaultValue?: R): OperatorFunction<T, T | R>;
export declare function defaultIfEmpty<T, R>(defaultValue: R): OperatorFunction<T, T | R>;

export declare function delay<T>(due: number | Date, scheduler?: SchedulerLike): MonoTypeOperatorFunction<T>;

Expand All @@ -86,7 +86,8 @@ export declare function distinctUntilChanged<T, K>(comparator: (previous: K, cur
export declare function distinctUntilKeyChanged<T>(key: keyof T): MonoTypeOperatorFunction<T>;
export declare function distinctUntilKeyChanged<T, K extends keyof T>(key: K, compare: (x: T[K], y: T[K]) => boolean): MonoTypeOperatorFunction<T>;

export declare function elementAt<T>(index: number, defaultValue?: T): MonoTypeOperatorFunction<T>;
export declare function elementAt<T, D>(index: number): MonoTypeOperatorFunction<T>;
export declare function elementAt<T, D>(index: number, defaultValue: D): OperatorFunction<T, T | D>;

export declare function endWith<T>(scheduler: SchedulerLike): MonoTypeOperatorFunction<T>;
export declare function endWith<T, A>(v1: A, scheduler: SchedulerLike): OperatorFunction<T, T | A>;
Expand Down
10 changes: 8 additions & 2 deletions spec-dtslint/operators/defaultIfEmpty-spec.ts
Original file line number Diff line number Diff line change
@@ -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<number>
const o = of(1, 2, 3).pipe(defaultIfEmpty()); // $ExpectError
const o2 = of(undefined).pipe(defaultIfEmpty(undefined)); // $ExpectType Observable<undefined>
});

it('should infer correctly with a defaultValue', () => {
Expand All @@ -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<number, string>('carbonara')); // $ExpectType Observable<string | number>
const o2 = of(1, 2, 3).pipe(defaultIfEmpty('carbonara')); // $ExpectType Observable<string | number>
});

it('should infer correctly with a subtype passed through parameters', () => {
Expand All @@ -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<never> appropriately', () => {
const o = EMPTY.pipe(defaultIfEmpty('blah')); // $ExpectType Observable<string>
})
19 changes: 4 additions & 15 deletions spec/operators/defaultIfEmpty-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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--|');
Expand All @@ -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);
});
});
Expand Down
10 changes: 3 additions & 7 deletions src/internal/operators/defaultIfEmpty.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<T, R = T>(defaultValue?: R): OperatorFunction<T, T | R>;
/* tslint:enable:max-line-length */

/**
* Emits a given value if the source Observable completes without emitting any
* `next` value, otherwise mirrors the source Observable.
Expand Down Expand Up @@ -34,13 +30,13 @@ export function defaultIfEmpty<T, R = T>(defaultValue?: R): OperatorFunction<T,
* @see {@link empty}
* @see {@link last}
*
* @param {any} [defaultValue=null] The default value used if the source
* @param defaultValue The default value used if the source
* Observable is empty.
* @return {Observable} An Observable that emits either the specified
* @return An Observable that emits either the specified
* `defaultValue` if the source Observable emits no items, or the values emitted
* by the source Observable.
*/
export function defaultIfEmpty<T, R>(defaultValue: R | null = null): OperatorFunction<T, T | R> {
export function defaultIfEmpty<T, R>(defaultValue: R): OperatorFunction<T, T | R> {
return operate((source, subscriber) => {
let hasValue = false;
source.subscribe(
Expand Down

0 comments on commit 4983760

Please sign in to comment.