I have the following model :
export interface IModel<T> {
exp: number,
value: T
}
I want to create a custom RxJS operator such as :
private customOperator<U extends A | B, T extends IModel<U>>(custom: Observable<T>): Observable<U> {
return custom.pipe(map((x: T) => x.value ));
}
But I Have a type error when using it :
mySub: = new Subject<IModel<A>>;
myObs$: Observable<A> = this.mySub.asObservable().pipe(this.customOperator); // <== ERROR
The error : Can't assign type 'Observable<A | B>' to type 'Observable< A>'.
Any idea on how I could change my custom operator to avoid the issue ?
CodePudding user response:
Wrap the operator in a factory function.
private customOperator<T extends IModel<U>, U extends A | B> () {
return (custom: Observable<T>): Observable<U> =>
custom.pipe(map((x: T) => x.value ));
}
And then in the pipe use the operator as a function call instead of the function ref.
myObs$: Observable<A> = this.mySub.asObservable().pipe(this.customOperator());
cheers
CodePudding user response:
You need to use the Typescript type assertion feature.
In your case the compiler complains because myObs$
must be of type Observable<A>
while your custom operator can return either an Observable<A>
or an Observable<B>
.
So if you want to avoid the error you need to reassure Typescript that your custom operator will certainly return an Observable<A>
. This is a trick to avoid a legitimate check of the Typescript compiler, so you better be sure you are doing the right thing.
So the code should look like this
myObs$: Observable<A> = this.mySub.asObservable().pipe(this.customOperator) as Observable<A>;
or, more simply
myObs$ = this.mySub.asObservable().pipe(this.customOperator) as Observable<A>;
If you hover over myObs$
, for instance within VSCode, you will see that the type inferred for myObs$
is actually Observable<A>
even if you have not specified the type (at least in this last version of the code)