ReactiveX / rxjs

A reactive programming library for JavaScript
https://rxjs.dev
Apache License 2.0
30.7k stars 3k forks source link

Typing for "Observable-y" returns #1248

Closed benlesh closed 7 years ago

benlesh commented 8 years ago

A Problem Of Return Typing

I'd like to examine functions such as mergeMap and switchMap... they take an argument that is like (value: T, index: number) => Observable<R> and we need something different, because Observable<R> could be a Promise<R> or R[] or Iterable<R> or Iterator<R> or observable<R> (which is a different type altogether, honestly).

IObservable-able

For one thing, there are two weird interfaces in there...

interface IObservableable {
  [Symbol.observable]() : IObservable<any>
}

interface IObservable<T> extends IObservableable {
  subscribe(observer?: Observer<T>) => Subscription
}

That is a mirror, basically of Iterable and Iterator in ES6.

Thoughts?

/cc @david-driscoll for expertise and @zenparsing for vernacular.

david-driscoll commented 8 years ago

So merged fairly recently are these types, though they are not used extensively yet. https://github.com/ReactiveX/RxJS/blob/master/src/Observable.ts#L40-L42, names can be changed, no point fighting over, because naming is hard™. They're derived from similar types in RxJS4 ( https://github.com/Reactive-Extensions/RxJS/blob/master/ts/core/es5.ts#L3-L8 ). I plan to progressively send PR's updating types as they move along.

Basic premise is that, ObservableInput<T> represents a value that can enter the system, with most operators, they get directed and enter through subscribeToResult. This can either be through a selector method (switchMap), or directly as an argument (combineLatest). The results of all these methods would all be Observable<T>, we just need a type that "describes" the inputs, hence why I named it ObservableInput<T>.

Today subscribeToResult clearly supports:

Now there are some cases where this may not be the "ideal" usage. For example, if I were to combineLatest an infinite Iterable bad things would probably happen. I don't know if we should try and author the typings such that we help users avoid a pitfall like that. To me I would think the types should document the full API. I'm sure there are possible use cases for using combineLatest with an Iterable, so I wouldn't want to exclude it from the API just because someone might do something wrong with an Iterable in the future.

Observableish

I'm not 100% on the spec with obserables, does the symbol return itself, or an observable instance? (I'll dig into it when I have time). Regardless something like the following could be added onto ObservableInput<T>:

interface IObservableable<T> {
  [Symbol.observable]() : IObservableLike<T>;
}

interface IObservableLike<T> extends IObservableable<T> {
  subscribe(observer?: Observer<T>) => Subscription;
}

...
// In `Observable.ts`
export class Observable extends IObservableLike<T> {
benlesh commented 8 years ago

bump for visibility

benlesh commented 7 years ago

closed for staleness

lock[bot] commented 6 years ago

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.