I was pretty excited about this typing for RxJS, since it does have a sort of "fluent" style interface. However we have some issues with it that are discussed here: https://github.com/ReactiveX/RxJS/issues/846
Basically, we have operators that return same-shaped, but different generic types:
map for example: Observable<T>.prototype.map<R>((value: T) => R): Observable<R>
The reason we were looking at this typing the above is that map doesn't always return an Observable, it could be called on a Subject which is a subclass of Observable. In that case, it actually returns a Subject, not an Observable, because of our fancy lift mechanism:
The Observable's lift:
https://github.com/ReactiveX/RxJS/blob/2896556afe8b663d4f983da1830fe407841e7d5b/src/Observable.ts#L51-L63
The Subject's lift:
https://github.com/ReactiveX/RxJS/blob/2896556afe8b663d4f983da1830fe407841e7d5b/src/Subject.ts#L37-L41
How lift is used (in map for example):
https://github.com/ReactiveX/RxJS/blob/2896556afe8b663d4f983da1830fe407841e7d5b/src/operators/map.ts#L17
It would be fantastic if we could provide our TypeScript users with the proper type information in their IDEs. Perhaps some additional syntax like this<R> would fit the bill? It's also worth noting that operators always return a new instance, rather than the same this instance, if that makes a difference.
I think this is another instance of the higher order generic referenced in: https://github.com/Microsoft/TypeScript/issues/1213 combined with this types. i think you want to say something like:
map<T<*> extends Observable<*>, R, U>(this: T<U>, fn: (value: U) => R): T<R>
@mhegazy that looks something like it yeah. My C# is rusty, but I think in C# it was something like map<T, R, U>(this: T<U>, fn: (value: U) => R) where T<U> : Observable<U> or the like.
I'm pretty sure C# doesn't support higher-kinded types either, so it'll fail at T<U>.
No - C# does not yet have higher-kinded types.
@weswigham bummer. Not that I think it would be too useful in C# in most cases. But since TypeScript has JavaScript as a build target, I think it would be useful here. Well, clearly, because we've hit the need.
@mhegazy, @blesh
for your example you do not need higher kinded types, f-bounded polymorphism is sufficient
your example can be expressed in C# as
static T map<T, R, U>(this T @this, Func<U, R> fn) where T : Observable<U> { ... }
which is an extension method
and in typescript (since 1.8 I think) as
map<T extends Observable<U>, R, U>(that: T, fn: (value: U) => R): T { ... }
which is unfortunately an ordinary function