Home > database >  RxJS Custom operator with typescript Union type
RxJS Custom operator with typescript Union type

Time:12-30

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)

  • Related