Reputation: 24953
I am trying to create an interface to make TypeScript
happy.
I am doing:
@Output() onChange:IMyEvent<ISliderItemData> = new Subject().delay(300).debounceTime(1000) ;// emits ISliderItemData
but I'm getting the following error:
Error:(68, 5) TS2322:Type 'Observable<{}>' is not assignable to type 'IMyEvent<ISliderItemData>'.
Property '__isAsync' is missing in type 'Observable<{}>'.
I tried to satisfy TS with the following code but it did not work:
class IMyEvent<T> extends Subject<T> {
__isAsync: boolean;
}
any ideas?
Upvotes: 0
Views: 872
Reputation: 14564
As you indicated,
@Output() onChange:IMyEvent<ISliderItemData> = new Subject().delay(300).debounceTime(1000) ;// emits ISliderItemData
You are taking a Subject and then calling the delay operator on it. At that point, you no longer have a Subject - you instead have an Observable. Any further operators chained onto that will also return Observables. Therefore, the result of your expression (i.e. the stuff on the right of the '=') is an Observable. Hence, Typescript expects your declaration on the right to be of a matching type i.e. an Observable.
So, the simplest form of this would be:
@Output() onChange: Observable = new Subject().delay(300).debounceTime(1000) ;// emits ISliderItemData
However, in your case, you want to type your onChange variable to indicate what type the Observable emits. You should also type your Subject so that it matches. So, this becomes:
@Output() onChange: Observable<ISliderItemData> = new Subject<ISliderItemData>().delay(300).debounceTime(1000) ;// emits ISliderItemData
The reality is that Typescript is pretty smart about inferring types based on usage, so you could actually use:
@Output() onChange = new Subject<ISliderItemData>().delay(300).debounceTime(1000) ;// emits ISliderItemData
The Typescript compiler will see that the return type of your delay operator (and resulting debounceTime operator) is Observable and automatically assign that type to your onChange instance variable.
It's personal preference in this case whether you bother to put the type on the onChange variable - it's not needed by the compiler but can be useful to add some code clarity.
Upvotes: 0
Reputation: 331
I did not test it but I would guess following might work:
@Output() onChange:IMyEvent<ISliderItemData> = <IMyEvent<ISliderItemData>>(new Subject().delay(300).debounceTime(1000)) ;
Why you don't define folloowing?
class IMyEvent<T> extends Observable<T> {
__isAsync: boolean;
}
and then using:
@Output() onChange:IMyEvent<ISliderItemData> = new IMyEvent<ISliderItemData>().delay(300).debounceTime(1000) ;
That would create typed Subject (and be converted to Observable by delay() and debounceTime())
Edit:
I have changed original answer - Subject
to IMyEvent
. On top - if I see the code and comments - I believe it would be better to keep clean Subject
to be able to call next()
as you need and use delay()
and debounceTime()
on consuming side.
Upvotes: 1
Reputation: 24953
So as @jonrsharpe said, you can do it on the push side, but if you want to do it at declaration, this will work:
@Output() onChange:Observable<ISliderItemData> = new Subject().delay(300).debounceTime(1000);
...
and later:
(this.onChange as Subject<ISliderItemData>).next({data})
Upvotes: 0