Search code examples
angularrxjsangular-upgrade

Angular 8.2 Type 'Subscription' is missing the following properties from type


I´m upgrading a legacy project from angular 7.2 to 8.2 and after it, when I execute ng serve it shows this error:

ERROR in app/service/broadcast.service.ts:21:5 - error TS2740: Type 'Subscription' is missing the following properties from type 'Subscriber': syncErrorValue, syncErrorThrown, syncErrorThrowable, isStopped, and 8 more.

21 return this.subscriber.subscribe(generator);

broadcast.service.ts

import {EventEmitter} from '@angular/core';
import {Injectable} from '@angular/core';
import {Subscriber} from 'rxjs';
import {BroadcastObject} from '../utils/interfaces/OnBroadcast.interface';

/**
 * BroadcastService: Simple service to broadcast object-like message between components
 */
@Injectable({
providedIn: 'root'
})
export class BroadcastService {
  public subscriber:EventEmitter<any>;
  constructor() {
    this.subscriber = new EventEmitter();
  }
  broadcast(name:string, data: any) {
    this.subscriber.emit({name, data});
  }
  subscribe(generator:Function):Subscriber<BroadcastObject> {
    return this.subscriber.subscribe(generator);
  }
}

OnBroadcast.interface.ts

export interface BroadcastObject {
 name:string;
 data:any;
}
export interface OnBroadcast {
 onBroadcast(data:BroadcastObject):any;
}

After googling I´ve tried by removing .subscribe(generator) part, but then console arrows this error:

ERROR in app/service/broadcast.service.ts:21:5 - error TS2740: Type 'EventEmitter' is missing the following properties from type 'Subscriber': syncErrorValue, syncErrorThrown, syncErrorThrowable, destination, and 10 more.

21 return this.subscriber;

Do you know how can I fix it?

Thanks


Solution

  • The typings don't look quite correct here. There are several possible things you could do:

    1. Change your subscribe method to return an rxjs Subscription:
    import { Subscription } from 'rxjs';
    ...
    subscribe(generator: Function): Subscription {
      return this.subscriber.subscribe(generator);
    }
    
    1. Refactor your subscribe method to just return the observable, and rely on the caller to subscribe:
    import { Observable } from 'rxjs';
    ...
    getObservable(): Observable<BroadcastObject> {
      return this.subscriber;
    }
    ...
    // in calling code:
    broadcastService.getObservable().subscribe(value => {
      // ...
    });
    

    The variable you have named subscriber is an Angular EventEmitter (which is basically a wrapper around an rxjs Subject): this means it acts like a data channel where you can send data into it using the emit method, and listen for data with the subscribe method. This subscribe method returns a Subscription which can be used to cancel the subscription via the unsubscribe method.