Skip to content

Commit

Permalink
Merge pull request #2373 from Podlas29/observable-input-docs
Browse files Browse the repository at this point in the history
docs(ObservableInput): add ObservableInput and SubscribableOrPromise descriptions
  • Loading branch information
jayphelps authored Feb 15, 2017
2 parents db8dc77 + 9c018b5 commit 7839002
Show file tree
Hide file tree
Showing 17 changed files with 238 additions and 20 deletions.
218 changes: 218 additions & 0 deletions src/MiscJSDoc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,221 @@ export class ObserverDoc<T> {
return void 0;
}
}

/**
* `SubscribableOrPromise` interface describes values that behave like either
* Observables or Promises. Every operator that accepts arguments annotated
* with this interface, can be also used with parameters that are not necessarily
* RxJS Observables.
*
* Following types of values might be passed to operators expecting this interface:
*
* ## Observable
*
* RxJS {@link Observable} instance.
*
* ## Observable-like (Subscribable)
*
* This might be any object that has `Symbol.observable` method. This method,
* when called, should return object with `subscribe` method on it, which should
* behave the same as RxJS `Observable.subscribe`.
*
* `Symbol.observable` is part of https://github.com/tc39/proposal-observable proposal.
* Since currently it is not supported natively, and every symbol is equal only to itself,
* you should use https://github.com/blesh/symbol-observable polyfill, when implementing
* custom Observable-likes.
*
* **TypeScript Subscribable interface issue**
*
* Although TypeScript interface claims that Subscribable is an object that has `subscribe`
* method declared directly on it, passing custom objects that have `subscribe`
* method but not `Symbol.observable` method will fail at runtime. Conversely, passing
* objects with `Symbol.observable` but without `subscribe` will fail at compile time
* (if you use TypeScript).
*
* TypeScript has problem supporting interfaces with methods defined as symbol
* properties. To get around that, you should implement `subscribe` directly on
* passed object, and make `Symbol.observable` method simply return `this`. That way
* everything will work as expected, and compiler will not complain. If you really
* do not want to put `subscribe` directly on your object, you will have to type cast
* it to `any`, before passing it to an operator.
*
* When this issue is resolved, Subscribable interface will only permit Observable-like
* objects with `Symbol.observable` defined, no matter if they themselves implement
* `subscribe` method or not.
*
* ## ES6 Promise
*
* Promise can be interpreted as Observable that emits value and completes
* when it is resolved or errors when it is rejected.
*
* ## Promise-like (Thenable)
*
* Promises passed to operators do not have to be native ES6 Promises.
* They can be implementations from popular Promise libraries, polyfills
* or even custom ones. They just need to have `then` method that works
* as the same as ES6 Promise `then`.
*
* @example <caption>Use merge and then map with non-RxJS observable</caption>
* const nonRxJSObservable = {
* subscribe(observer) {
* observer.next(1000);
* observer.complete();
* },
* [Symbol.observable]() {
* return this;
* }
* };
*
* Rx.Observable.merge(nonRxJSObservable)
* .map(value => "This value is " + value)
* .subscribe(result => console.log(result)); // Logs "This value is 1000"
*
*
* @example <caption>Use combineLatest with ES6 Promise</caption>
* Rx.Observable.combineLatest(Promise.resolve(5), Promise.resolve(10), Promise.resolve(15))
* .subscribe(
* value => console.log(value),
* err => {},
* () => console.log('the end!')
* );
* // Logs
* // [5, 10, 15]
* // "the end!"
*
*
* @interface
* @name SubscribableOrPromise
* @noimport true
*/
export class SubscribableOrPromiseDoc<T> {

}

/**
* `ObservableInput` interface describes all values that are either an
* {@link SubscribableOrPromise} or some kind of collection of values that
* can be transformed to Observable emitting that values. Every operator that
* accepts arguments annotated with this interface, can be also used with
* parameters that are not necessarily RxJS Observables.
*
* `ObservableInput` extends {@link SubscribableOrPromise} with following types:
*
* ## Array
*
* Arrays can be interpreted as observables that emit all values in array one by one,
* from left to right, and then complete immediately.
*
* ## Array-like
*
* Arrays passed to operators do not have to be built-in JavaScript Arrays. They
* can be also, for example, `arguments` property available inside every function,
* [DOM NodeList](https://developer.mozilla.org/pl/docs/Web/API/NodeList),
* or, actually, any object that has `length` property (which is a number)
* and stores values under non-negative (zero and up) integers.
*
* ## ES6 Iterable
*
* Operators will accept both built-in and custom ES6 Iterables, by treating them as
* observables that emit all its values in order of iteration and then complete
* when iteration ends. Note that contrary to arrays, Iterables do not have to
* necessarily be finite, so creating Observables that never complete is possible as well.
*
* Note that you can make iterator an instance of Iterable by having it return itself
* in `Symbol.iterator` method. It means that every operator accepting Iterables accepts,
* though indirectly, iterators themselves as well. All native ES6 iterators are instances
* of Iterable by default, so you do not have to implement their `Symbol.iterator` method
* yourself.
*
* **TypeScript Iterable interface issue**
*
* TypeScript `ObservableInput` interface actually lacks type signature for Iterables,
* because of issues it caused in some projects (see [this issue](https://github.com/ReactiveX/rxjs/issues/2306)).
* If you want to use Iterable as argument for operator, cast it to `any` first.
* Remember of course that, because of casting, you have to yourself ensure that passed
* argument really implements said interface.
*
*
* @example <caption>Use merge with arrays</caption>
* Rx.Observable.merge([1, 2], [4], [5, 6])
* .subscribe(
* value => console.log(value),
* err => {},
* () => console.log('ta dam!')
* );
*
* // Logs
* // 1
* // 2
* // 3
* // 4
* // 5
* // 6
* // "ta dam!"
*
*
* @example <caption>Use merge with array-like</caption>
* Rx.Observable.merge({0: 1, 1: 2, length: 2}, {0: 3, length: 1})
* .subscribe(
* value => console.log(value),
* err => {},
* () => console.log('nice, huh?')
* );
*
* // Logs
* // 1
* // 2
* // 3
* // "nice, huh?"
*
* @example <caption>Use merge with an Iterable (Map)</caption>
* const firstMap = new Map([[1, 'a'], [2, 'b']]);
* const secondMap = new Map([[3, 'c'], [4, 'd']]);
*
* Rx.Observable.merge(
* firstMap, // pass Iterable
* secondMap.values() // pass iterator, which is itself an Iterable
* ).subscribe(
* value => console.log(value),
* err => {},
* () => console.log('yup!')
* );
*
* // Logs
* // [1, "a"]
* // [2, "b"]
* // "c"
* // "d"
* // "yup!"
*
* @example <caption>Use from with generator (returning infinite iterator)</caption>
* // infinite stream of incrementing numbers
* const infinite = function* () {
* let i = 0;
*
* while (true) {
* yield i++;
* }
* };
*
* Rx.Observable.from(infinite())
* .take(3) // only take 3, cause this is infinite
* .subscribe(
* value => console.log(value),
* err => {},
* () => console.log('ta dam!')
* );
*
* // Logs
* // 0
* // 1
* // 2
* // "ta dam!"
*
* @interface
* @name ObservableInput
* @noimport true
*/
export class ObservableInputDoc<T> {

}
2 changes: 1 addition & 1 deletion src/observable/DeferObservable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export class DeferObservable<T> extends Observable<T> {
*
* @see {@link create}
*
* @param {function(): Observable|Promise} observableFactory The Observable
* @param {function(): SubscribableOrPromise} observableFactory The Observable
* factory function to invoke for each Observer that subscribes to the output
* Observable. May also return a Promise, which will be converted on the fly
* to an Observable.
Expand Down
4 changes: 2 additions & 2 deletions src/observable/combineLatest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ export function combineLatest<R>(...observables: Array<ObservableInput<any> | ((
* @see {@link merge}
* @see {@link withLatestFrom}
*
* @param {Observable} observable1 An input Observable to combine with the
* @param {ObservableInput} observable1 An input Observable to combine with the
* source Observable.
* @param {Observable} observable2 An input Observable to combine with the
* @param {ObservableInput} observable2 An input Observable to combine with the
* source Observable. More than one input Observables may be given as argument.
* @param {function} [project] An optional function to project the values from
* the combined latest values into a new value on the output Observable.
Expand Down
2 changes: 1 addition & 1 deletion src/operator/audit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import { subscribeToResult } from '../util/subscribeToResult';
* @see {@link sample}
* @see {@link throttle}
*
* @param {function(value: T): Observable|Promise} durationSelector A function
* @param {function(value: T): SubscribableOrPromise} durationSelector A function
* that receives a value from the source Observable, for computing the silencing
* duration, returned as an Observable or a Promise.
* @return {Observable<T>} An Observable that performs rate-limiting of
Expand Down
2 changes: 1 addition & 1 deletion src/operator/combineLatest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export function combineLatest<T, TOther, R>(this: Observable<T>, array: Observab
* @see {@link merge}
* @see {@link withLatestFrom}
*
* @param {Observable} other An input Observable to combine with the source
* @param {ObservableInput} other An input Observable to combine with the source
* Observable. More than one input Observables may be given as argument.
* @param {function} [project] An optional function to project the values from
* the combined latest values into a new value on the output Observable.
Expand Down
6 changes: 3 additions & 3 deletions src/operator/concat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export function concat<T, R>(this: Observable<T>, ...observables: Array<Observab
* @see {@link concatMap}
* @see {@link concatMapTo}
*
* @param {Observable} other An input Observable to concatenate after the source
* @param {ObservableInput} other An input Observable to concatenate after the source
* Observable. More than one input Observables may be given as argument.
* @param {Scheduler} [scheduler=null] An optional IScheduler to schedule each
* Observable subscription on.
Expand Down Expand Up @@ -117,8 +117,8 @@ export function concatStatic<T, R>(...observables: (ObservableInput<any> | ISche
* @see {@link concatMap}
* @see {@link concatMapTo}
*
* @param {Observable} input1 An input Observable to concatenate with others.
* @param {Observable} input2 An input Observable to concatenate with others.
* @param {ObservableInput} input1 An input Observable to concatenate with others.
* @param {ObservableInput} input2 An input Observable to concatenate with others.
* More than one input Observables may be given as argument.
* @param {Scheduler} [scheduler=null] An optional IScheduler to schedule each
* Observable subscription on.
Expand Down
2 changes: 1 addition & 1 deletion src/operator/concatMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export function concatMap<T, I, R>(this: Observable<T>, project: (value: T, inde
* @see {@link mergeMap}
* @see {@link switchMap}
*
* @param {function(value: T, ?index: number): Observable} project A function
* @param {function(value: T, ?index: number): ObservableInput} project A function
* that, when applied to an item emitted by the source Observable, returns an
* Observable.
* @param {function(outerValue: T, innerValue: I, outerIndex: number, innerIndex: number): any} [resultSelector]
Expand Down
2 changes: 1 addition & 1 deletion src/operator/concatMapTo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export function concatMapTo<T, I, R>(this: Observable<T>, observable: Observable
* @see {@link mergeMapTo}
* @see {@link switchMapTo}
*
* @param {Observable} innerObservable An Observable to replace each value from
* @param {ObservableInput} innerObservable An Observable to replace each value from
* the source Observable.
* @param {function(outerValue: T, innerValue: I, outerIndex: number, innerIndex: number): any} [resultSelector]
* A function to produce the value on the output Observable based on the values
Expand Down
2 changes: 1 addition & 1 deletion src/operator/debounce.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import { subscribeToResult } from '../util/subscribeToResult';
* @see {@link delayWhen}
* @see {@link throttle}
*
* @param {function(value: T): Observable|Promise} durationSelector A function
* @param {function(value: T): SubscribableOrPromise} durationSelector A function
* that receives a value from the source Observable, for computing the timeout
* duration for each source value, returned as an Observable or a Promise.
* @return {Observable} An Observable that delays the emissions of the source
Expand Down
2 changes: 1 addition & 1 deletion src/operator/exhaustMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export function exhaustMap<T, I, R>(this: Observable<T>, project: (value: T, ind
* @see {@link mergeMap}
* @see {@link switchMap}
*
* @param {function(value: T, ?index: number): Observable} project A function
* @param {function(value: T, ?index: number): ObservableInput} project A function
* that, when applied to an item emitted by the source Observable, returns an
* Observable.
* @param {function(outerValue: T, innerValue: I, outerIndex: number, innerIndex: number): any} [resultSelector]
Expand Down
4 changes: 2 additions & 2 deletions src/operator/merge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export function merge<T, R>(this: Observable<T>, ...observables: Array<Observabl
* @see {@link mergeMapTo}
* @see {@link mergeScan}
*
* @param {Observable} other An input Observable to merge with the source
* @param {ObservableInput} other An input Observable to merge with the source
* Observable. More than one input Observables may be given as argument.
* @param {number} [concurrent=Number.POSITIVE_INFINITY] Maximum number of input
* Observables being subscribed to concurrently.
Expand Down Expand Up @@ -136,7 +136,7 @@ export function mergeStatic<T, R>(...observables: (ObservableInput<any> | ISched
* @see {@link mergeMapTo}
* @see {@link mergeScan}
*
* @param {...Observable} observables Input Observables to merge together.
* @param {...ObservableInput} observables Input Observables to merge together.
* @param {number} [concurrent=Number.POSITIVE_INFINITY] Maximum number of input
* Observables being subscribed to concurrently.
* @param {Scheduler} [scheduler=null] The IScheduler to use for managing
Expand Down
2 changes: 1 addition & 1 deletion src/operator/mergeMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export function mergeMap<T, I, R>(this: Observable<T>, project: (value: T, index
* @see {@link mergeScan}
* @see {@link switchMap}
*
* @param {function(value: T, ?index: number): Observable} project A function
* @param {function(value: T, ?index: number): ObservableInput} project A function
* that, when applied to an item emitted by the source Observable, returns an
* Observable.
* @param {function(outerValue: T, innerValue: I, outerIndex: number, innerIndex: number): any} [resultSelector]
Expand Down
2 changes: 1 addition & 1 deletion src/operator/mergeMapTo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function mergeMapTo<T, I, R>(this: Observable<T>, observable: ObservableI
* @see {@link mergeScan}
* @see {@link switchMapTo}
*
* @param {Observable} innerObservable An Observable to replace each value from
* @param {ObservableInput} innerObservable An Observable to replace each value from
* the source Observable.
* @param {function(outerValue: T, innerValue: I, outerIndex: number, innerIndex: number): any} [resultSelector]
* A function to produce the value on the output Observable based on the values
Expand Down
2 changes: 1 addition & 1 deletion src/operator/switchMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export function switchMap<T, I, R>(this: Observable<T>, project: (value: T, inde
* @see {@link switch}
* @see {@link switchMapTo}
*
* @param {function(value: T, ?index: number): Observable} project A function
* @param {function(value: T, ?index: number): ObservableInput} project A function
* that, when applied to an item emitted by the source Observable, returns an
* Observable.
* @param {function(outerValue: T, innerValue: I, outerIndex: number, innerIndex: number): any} [resultSelector]
Expand Down
2 changes: 1 addition & 1 deletion src/operator/switchMapTo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export function switchMapTo<T, I, R>(this: Observable<T>, observable: Observable
* @see {@link switchMap}
* @see {@link mergeMapTo}
*
* @param {Observable} innerObservable An Observable to replace each value from
* @param {ObservableInput} innerObservable An Observable to replace each value from
* the source Observable.
* @param {function(outerValue: T, innerValue: I, outerIndex: number, innerIndex: number): any} [resultSelector]
* A function to produce the value on the output Observable based on the values
Expand Down
2 changes: 1 addition & 1 deletion src/operator/throttle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import { subscribeToResult } from '../util/subscribeToResult';
* @see {@link sample}
* @see {@link throttleTime}
*
* @param {function(value: T): Observable|Promise} durationSelector A function
* @param {function(value: T): SubscribableOrPromise} durationSelector A function
* that receives a value from the source Observable, for computing the silencing
* duration for each source value, returned as an Observable or a Promise.
* @return {Observable<T>} An Observable that performs the throttle operation to
Expand Down
2 changes: 1 addition & 1 deletion src/operator/withLatestFrom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export function withLatestFrom<T, R>(this: Observable<T>, array: ObservableInput
*
* @see {@link combineLatest}
*
* @param {Observable} other An input Observable to combine with the source
* @param {ObservableInput} other An input Observable to combine with the source
* Observable. More than one input Observables may be given as argument.
* @param {Function} [project] Projection function for combining values
* together. Receives all values in order of the Observables passed, where the
Expand Down

0 comments on commit 7839002

Please sign in to comment.