-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Extending Observable - static of
method
#1876
Comments
@Blesh I think you actually mean static of(...values) {
const observable = new this();
const scheduler = undefined;
if (values[values.length - 1] instanceof Scheduler) {
scheduler = values.pop();
}
observable.source = new ArrayObservable(values, scheduler);
return observable;
} My initial testing suggests that TypeScript is perfectly fine with this approach. It knows what type |
What if implicitly declare variable in demo such as
|
I refer this , implicit variable class ActionsObservable extends Observable {
test(): void {
console.log('meh');
}
}
const action$ = ActionsObservable.of();
action$.test(); //Typescript can't infer method in inherited class |
shit... Yep, known issue microsoft/TypeScript#5863 |
Another thing about this approach is it would add a layer of indirection for the basic That would incur a definite performance hit. |
Using generics we could provide an ugly ass workaround.... class Observable {
static of<T extends Observable>(): Observable & T {
return new this() as Observable & T;
}
}
class ActionsObservable extends Observable {
test(): void {
console.log('meh');
}
}
const action$ = ActionsObservable.of<ActionsObservable>();
action$.test(); If we did such a thing, prolly would want to be a signature overload, so people can just omit the generic type for the default base type. I don't love this...but given how many people don't use TS we can't let it always limit our decisions. Particularly because they'll very likely support polymorphism on this eventually. The perf hit is the biggest argument against IMO. We'll need to run the test suite and see how much of a hit it ends up actually being. We could be overly clever and only go down this path when needed... static of(...values) {
// etc...
const source = new ArrayObservable(values, scheduler);
if (this === undefined || this === Observable) {
return source;
} else {
const observable = new this();
observable.source = source;
return observable;
}
} The real code is more complex than that. I'm not sure where I land on all of this. I really want this ability..just not confident this is the best approach atm. |
I've also used the |
I wouldn't let TS limit our decisions unless it was going to result in something horribly unergonomic for the large number of Angular 2 users that are using RxJS 5. It seems like it's a known issue in TypeScript and they're working to resolve it. So I don't think we need any crazy TypeScript workarounds. No reason to junk up code any more than we have for typings issues. We probably just want to document it for the TypeScript users and reference that issue. |
Hello, I posted a solution to this approach that works with typescript >= 2.0 on microsoft/TypeScript#5863 if you're interested |
interface IObservableClass<T extends Observable> {
new (...a: any[]): T
// ... + other static methods/members of Observable
}
class Observable {
// The `this:` is the important part here
static of<T extends Observable>(this: IObservableClass<T>): T {
return new this();
}
}
class ActionsObservable extends Observable {
test(): void {
console.log('meh');
}
}
// voilà, no more type specification !
const action$ = ActionsObservable.of();
// acion$ is an ActionsObservable, test() is now known.
action$.test(); |
@ceymard very cool. I worry about the interop story if we upgrade to TS 2.0 too early. I imagine users of 1.x would be SOL. |
@jayphelps I expect adapt 2.0 probably considerable after official public release + ng2's compiler upgrade schedule, as same as introducing 1.8 for module augmentation. |
I tried this myself and it seems there isn't a perfect solution for type definition to support this. Below is code snippet shows it, export interface ObservableCtor<X, U extends Observable<X>> {
new(): U;
}
class Observable<T> {
static of<R, U extends Observable<R>>(this: ObservableCtor<R, U>, ...args: Array<R>): U {
return new this();
}
static ofBaseType<R, U extends Observable<R>>(this: ObservableCtor<R, U>, ...args: Array<R>): Observable<R> {
return new this();
}
}
class ActionsObservable<T> extends Observable<T> {}
let c1 = Observable.of(42); //Observable<any>
let c2 = ActionsObservable.of(42); //ActionsObservable<any>
let c3: ActionsObservable<number> = ActionsObservable.of(42); //forcing, supplying correct type
let c4 = ActionsObservable.of<number, ActionsObservable<number>>(42); //forcing, supplying correct type
let b1 = Observable.ofBaseType(42); //Observable<number>
let b2 = ActionsObservable.ofBaseType(42); //Observable<number> This is because TS currently does not support higher order generic constraint, so there isn't a way to force note : on TS 2.0.7, 2.1.4 both. |
Closing as stale. |
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. |
While talking with @jayphelps about ActionsObservable from redux-observable/redux-observable, it's come up once or twice that someone would need to create an
ActionsObservable
from an array or set of values...Currently, this means you have to manually override
static of
in the ActionsObservable if you want to get anActionsObservable
as a result.I think we could possibly change the static of method to do something like this:
This would mean that extended classes like
ActionsObservable
would be able to benefit fromof
without needing to override it.Risks
Subject
withSubject.of
.Workaround
The current workaround if you needed this sort of thing is to simply implement
static of
yourself, (which is basically the same as above):It's perhaps just a little gross to have to do this?
The text was updated successfully, but these errors were encountered: