Open flensrocker opened 2 weeks ago
I would love @benlesh's thoughts on this, as I learned about the possibly type issues with what was my default understanding of how developers would solve this: by patching the prototype.
RxJS is already moving this direction. Version 8 (still alpha) added an rx
function that effectively is just this:
function rx(source, ...fns) {
return from(source).pipe(...fns);
}
So with this, RxJS 8 (once using native observable types) will have a function that is implemented like so:
function rx(source, ...fns) {
const o = Observable.from(source);
return fns.reduce((prev, fn) => fn(prev), o);
}
This allows you to write functions in the "pipeable" way and use them.
function mapTwice(fn) {
return (source) => source.map(fn).map(fn)
}
function nevermindJustComplete() {
return (source) => new Observable(subscriber => {
source.subscribe({ next: () => subscriber.complete() }, { signal: subscriber.signal });
});
}
rx(someObservable, mapTwice(x => x + x), nevermindJustComplete())
Of course, the native functions will need pipeable analogs, which a library like RxJS can provide.
For iterator helpers, I'm considering proposing an Iterator.prototype.into
which is literally just Iterator.prototype.into = function (f) { return f(this); }
.
Then you could do
array.values()
.map(whatever)
.into(function*(iter) {
for (let item of iter) {
yield item + 1;
}
})
.filter(etc)
(Or .into
any other function which takes an iterator or iteraable, of course.)
Something to consider here, maybe?
Of course, the native functions will need pipeable analogs, which a library like RxJS can provide.
Or should they be static functions on Observable
? Or would that be too confusing as it makes not really sense to provide them on the platform?
Looking forward to rxjs 8! 🙂 Since I will use rxjs anyway, this will be ok for me.
Thank you!
How about providing a pipe
method to the built-in API in order to make seamless extensibility with the ecosystem?
import { operatorX as operatorXLibA } from 'libA'
import { operatorX as operatorXLibB } from 'libB'
array.values()
.map(whatever) // native
.filter(whatever) // native
.pipe(
// either, or, or even both:
operatorXLibA(whatever),
operatorXLibB(whatever)
)
.map(whatever) // native
How about providing a
pipe
method to the built-in API in order to make seamless extensibility with the ecosystem?import { operatorX as operatorXLibA } from 'libA' import { operatorX as operatorXLibB } from 'libB' array.values() .map(whatever) // native .filter(whatever) // native .pipe( // either, or, or even both: operatorXLibA(whatever), operatorXLibB(whatever) ) .map(whatever) // native
I'd like that too! Basic operators could be within the prototype + another method would let us create and use our own operators like we would with the rxjs pipe
My context: Angular application developer since v2, so I have seen various versions of rxjs etc. (but also forgot how it worked in the past).
In my applications I tend to write some custom operators to encapsulate some reusable behaviour. How is the implementation story with this API?
Extending the prototype (something I'm not very familiar with) seems to be a source of conflict, if different libraries would like to provide custom operators.
rxjs introduced the pipe function to easily chain operators to new "higher" operators, which also helps me as a TypeScript user to get the right types further down the chain.
(Thanks for this API to all involved. I really appreciate this and am looking forward to finally be able to combine different libraries with their different observable implementations!)