diff --git a/compat/operator/publishBehavior.ts b/compat/operator/publishBehavior.ts index 3919ea4283b..5b93bb1580e 100644 --- a/compat/operator/publishBehavior.ts +++ b/compat/operator/publishBehavior.ts @@ -8,5 +8,5 @@ import { publishBehavior as higherOrder } from 'rxjs/operators'; * @owner Observable */ export function publishBehavior(this: Observable, value: T): ConnectableObservable { - return higherOrder(value)(this); + return higherOrder(value)(this) as ConnectableObservable; } diff --git a/package-lock.json b/package-lock.json index b98c5c56eb7..a80dd47c77e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4972,7 +4972,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -5387,7 +5388,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -5443,6 +5445,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -5486,12 +5489,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -10947,9 +10952,9 @@ "dev": true }, "typescript": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.0.1.tgz", - "integrity": "sha512-zQIMOmC+372pC/CCVLqnQ0zSBiY7HHodU7mpQdjiZddek4GMj31I3dUJ7gAs9o65X7mnRma6OokOkc6f9jjfBg==", + "version": "3.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.4.5.tgz", + "integrity": "sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw==", "dev": true }, "underscore": { diff --git a/package.json b/package.json index ec9b6ab31c1..cdf7a00a703 100644 --- a/package.json +++ b/package.json @@ -215,7 +215,7 @@ "tslint-etc": "1.5.0", "tslint-no-toplevel-property-access": "0.0.2", "tslint-no-unused-expression-chai": "0.0.3", - "typescript": "^3.0.1", + "typescript": "^3.4.5", "validate-commit-msg": "2.14.0", "webpack": "^4.31.0" }, diff --git a/spec-dtslint/operators/publish-spec.ts b/spec-dtslint/operators/publish-spec.ts index d68ef8331f5..64fc468a3d3 100644 --- a/spec-dtslint/operators/publish-spec.ts +++ b/spec-dtslint/operators/publish-spec.ts @@ -2,11 +2,7 @@ import { of, Observable } from 'rxjs'; import { publish } from 'rxjs/operators'; it('should support empty parameter', () => { - // Here, TypeScript versions 3.1 and earlier infer Observable. However, - // the next version infers Observable. It's not possible to specify - // an upper bound for the TypeScript version used by dtslint, so an - // expectation cannot be applied. - const a = of(1, 2, 3).pipe(publish()); // $ExpectType Observable + const a = of(1, 2, 3).pipe(publish()); // $ExpectType Observable }); it('should infer when type is specified', () => { diff --git a/spec-dtslint/operators/publishBehavior-spec.ts b/spec-dtslint/operators/publishBehavior-spec.ts index e3d3a8a59a6..643393c9045 100644 --- a/spec-dtslint/operators/publishBehavior-spec.ts +++ b/spec-dtslint/operators/publishBehavior-spec.ts @@ -1,5 +1,5 @@ import { of } from 'rxjs'; -import { publishBehavior } from 'rxjs/operators'; +import { publishBehavior, map } from 'rxjs/operators'; it('should enforce parameter', () => { const a = of(1, 2, 3).pipe(publishBehavior()); // $ExpectError @@ -10,5 +10,10 @@ it('should infer correctly with parameter', () => { }); it('should enforce type on parameter', () => { - const a = of(1, 2, 3).pipe(publishBehavior('a'); // $ExpectError + const a = of(1, 2, 3).pipe(publishBehavior('a')); // $ExpectType Observable +}); + +it('should compose properly', () => { + const fn = () => Math.random() > 0.5; + const a = of(true, false).pipe(map(x => x && fn()), publishBehavior(false)); // $ExpectType Observable }); diff --git a/spec-dtslint/operators/publishLast-spec.ts b/spec-dtslint/operators/publishLast-spec.ts index 642f5e08981..22928a5f575 100644 --- a/spec-dtslint/operators/publishLast-spec.ts +++ b/spec-dtslint/operators/publishLast-spec.ts @@ -2,11 +2,7 @@ import { of } from 'rxjs'; import { publishLast } from 'rxjs/operators'; it('should accept empty parameter', () => { - // Here, TypeScript versions 3.1 and earlier infer Observable. However, - // the next version infers Observable. It's not possible to specify - // an upper bound for the TypeScript version used by dtslint, so an - // expectation cannot be applied. - const a = of(1, 2, 3).pipe(publishLast()); // $ExpectType Observable + const a = of(1, 2, 3).pipe(publishLast()); // $ExpectType Observable }); it('should infer when type is specified', () => { diff --git a/spec/operators/multicast-spec.ts b/spec/operators/multicast-spec.ts index a01f762a01b..84d00b73f00 100644 --- a/spec/operators/multicast-spec.ts +++ b/spec/operators/multicast-spec.ts @@ -703,49 +703,4 @@ describe('multicast operator', () => { }); }); }); - - describe('typings', () => { - type('should infer the type', () => { - /* tslint:disable:no-unused-variable */ - const source = of(1, 2, 3); - const result: ConnectableObservable = source.pipe(multicast(() => new Subject())) as ConnectableObservable; - /* tslint:enable:no-unused-variable */ - }); - - type('should infer the type with a selector', () => { - /* tslint:disable:no-unused-variable */ - const source = of(1, 2, 3); - const result: Observable = source.pipe(multicast(() => new Subject(), s => s.pipe(map(x => x)))); - /* tslint:enable:no-unused-variable */ - }); - - type('should infer the type with a type-changing selector', () => { - /* tslint:disable:no-unused-variable */ - const source = of(1, 2, 3); - const result: Observable = source.pipe(multicast(() => new Subject(), s => s.pipe(map(x => x + '!')))); - /* tslint:enable:no-unused-variable */ - }); - - type('should infer the type for the pipeable operator', () => { - /* tslint:disable:no-unused-variable */ - const source = of(1, 2, 3); - // TODO: https://github.com/ReactiveX/rxjs/issues/2972 - const result: ConnectableObservable = multicast(() => new Subject())(source); - /* tslint:enable:no-unused-variable */ - }); - - type('should infer the type for the pipeable operator with a selector', () => { - /* tslint:disable:no-unused-variable */ - const source = of(1, 2, 3); - const result: Observable = source.pipe(multicast(() => new Subject(), s => s.pipe(map(x => x)))); - /* tslint:enable:no-unused-variable */ - }); - - type('should infer the type for the pipeable operator with a type-changing selector', () => { - /* tslint:disable:no-unused-variable */ - const source = of(1, 2, 3); - const result: Observable = source.pipe(multicast(() => new Subject(), s => s.pipe(map(x => x + '!')))); - /* tslint:enable:no-unused-variable */ - }); - }); }); diff --git a/src/internal/operators/multicast.ts b/src/internal/operators/multicast.ts index 3531745db39..e45de0b09d3 100644 --- a/src/internal/operators/multicast.ts +++ b/src/internal/operators/multicast.ts @@ -3,12 +3,12 @@ import { Operator } from '../Operator'; import { Subscriber } from '../Subscriber'; import { Observable } from '../Observable'; import { ConnectableObservable, connectableObservableDescriptor } from '../observable/ConnectableObservable'; -import { OperatorFunction, UnaryFunction, ObservedValueOf, ObservableInput } from '../types'; +import { OperatorFunction, UnaryFunction, ObservedValueOf, ObservableInput, MonoTypeOperatorFunction } from '../types'; /* tslint:disable:max-line-length */ -export function multicast(subject: Subject): UnaryFunction, ConnectableObservable>; -export function multicast>(subject: Subject, selector: (shared: Observable) => O): UnaryFunction, ConnectableObservable>>; -export function multicast(subjectFactory: (this: Observable) => Subject): UnaryFunction, ConnectableObservable>; +export function multicast(subject: Subject): MonoTypeOperatorFunction; +export function multicast>(subject: Subject, selector: (shared: Observable) => O): OperatorFunction>; +export function multicast(subjectFactory: (this: Observable) => Subject): MonoTypeOperatorFunction; export function multicast>(SubjectFactory: (this: Observable) => Subject, selector: (shared: Observable) => O): OperatorFunction>; /* tslint:enable:max-line-length */ diff --git a/src/internal/operators/publish.ts b/src/internal/operators/publish.ts index e4596f30daa..ac29664b257 100644 --- a/src/internal/operators/publish.ts +++ b/src/internal/operators/publish.ts @@ -5,7 +5,7 @@ import { ConnectableObservable } from '../observable/ConnectableObservable'; import { MonoTypeOperatorFunction, OperatorFunction, UnaryFunction, ObservableInput, ObservedValueOf } from '../types'; /* tslint:disable:max-line-length */ -export function publish(): UnaryFunction, ConnectableObservable>; +export function publish(): MonoTypeOperatorFunction; export function publish>(selector: (shared: Observable) => O): OperatorFunction>; export function publish(selector: MonoTypeOperatorFunction): MonoTypeOperatorFunction; /* tslint:enable:max-line-length */ diff --git a/src/internal/operators/publishBehavior.ts b/src/internal/operators/publishBehavior.ts index 792b3151d01..b7b17c032a0 100644 --- a/src/internal/operators/publishBehavior.ts +++ b/src/internal/operators/publishBehavior.ts @@ -1,15 +1,21 @@ import { Observable } from '../Observable'; import { BehaviorSubject } from '../BehaviorSubject'; import { multicast } from './multicast'; -import { ConnectableObservable } from '../observable/ConnectableObservable'; -import { UnaryFunction } from '../types'; +import { OperatorFunction } from '../types'; /** - * @param value + * Multicasts the observable source through an underlying {@link BehaviorSubject}. All subscriptions + * to the resulting observable will subscribe to the underlaying `BehaviorSubject`, the + * resulting observable is a {@link ConnectableObservable}. If you call `connect()` on that observable + * (requires a cast to `ConnectableObservable` in TypeScript), it will subscribe to the source + * observable with the underlying subject and connect that source too all consumers subscribed through the + * subject. Because it's using a `BehaviorSubject`, all new subscriptions will get the most recent value + * that has passed through said subject, _or_ they will get the `initialValue` if no values have + * arrived yet, so long as the published `ConnectableObservable` has been connected. + * + * @param initialValue * @return {ConnectableObservable} - * @method publishBehavior - * @owner Observable */ -export function publishBehavior(value: T): UnaryFunction, ConnectableObservable> { - return (source: Observable) => multicast(new BehaviorSubject(value))(source) as ConnectableObservable; +export function publishBehavior(initialValue: D): OperatorFunction { + return (source: Observable) => multicast(new BehaviorSubject(initialValue))(source); } diff --git a/src/internal/operators/publishLast.ts b/src/internal/operators/publishLast.ts index e431657cb48..a8f96e023d8 100644 --- a/src/internal/operators/publishLast.ts +++ b/src/internal/operators/publishLast.ts @@ -2,7 +2,7 @@ import { Observable } from '../Observable'; import { AsyncSubject } from '../AsyncSubject'; import { multicast } from './multicast'; import { ConnectableObservable } from '../observable/ConnectableObservable'; -import { UnaryFunction } from '../types'; +import { UnaryFunction, MonoTypeOperatorFunction } from '../types'; /** * Returns a connectable observable sequence that shares a single subscription to the @@ -62,6 +62,6 @@ import { UnaryFunction } from '../types'; * @owner Observable */ -export function publishLast(): UnaryFunction, ConnectableObservable> { +export function publishLast(): MonoTypeOperatorFunction { return (source: Observable) => multicast(new AsyncSubject())(source); }