Search code examples
angulartypescriptrxjsangular11

Angular 11 with rxjs issue - TS2769: No overload matches this call


I would like to subscribe to NavigationEnd events in Angular 11, while using filter from rxjs.

The part of subscribe((event: NavigationEnd) ... causes the following issue

Current solution:

TS2769: No overload matches this call.   Overload 1 of 5, '(observer?: NextObserver | ErrorObserver | CompletionObserver | undefined): Subscription', gave the following error.     Argument of type '(event: NavigationEnd) => void' is not assignable to parameter of type 'NextObserver | ErrorObserver | CompletionObserver | undefined'.       Property 'complete' is missing in type '(event: NavigationEnd) => void' but required in type 'CompletionObserver'.   Overload 2 of 5, '(next?: ((value: Event) => void) | undefined, error?: ((error: any) => void) | undefined, complete?: (() => void) | undefined): Subscription', gave the following error.     Argument of type '(event: NavigationEnd) => void' is not assignable to parameter of type '(value: Event) => void'.       Types of parameters 'event' and 'value' are incompatible.         Type 'Event' is not assignable to type 'NavigationEnd'.           Property 'urlAfterRedirects' is missing in type 'RouterEvent' but required in type 'NavigationEnd'.

See constructor code below with mentioned code snippet:

export class NavigationService implements OnDestroy {
  private readonly routeChange: Subscription | undefined;
  private previousUrl: string | undefined;
  private ignoredRoutes = ['/signup', '/login', '/reset'];

  constructor(private router: Router) {
    this.routeChange = router.events
      .pipe(filter(event => event instanceof NavigationEnd))
      .subscribe((event: NavigationEnd) => {
        if (!this.ignoredRoutes.includes(event.url)) {
          this.previousUrl = event.url;
        }
      });
  }

  ngOnDestroy(): void {
    if (this.routeChange) {
      this.routeChange.unsubscribe();
    }
  }

  public routeToPreviousContent(): void {
    //route home if undefined
    const targetUrl = this.previousUrl ? this.previousUrl : '';
    this.router.navigate([targetUrl]).then();
  }
}

Is TS2769 valid in this case at all? I assume the rxjs filter pipe with the event instanceof NavigationEnd is simply not recognized?!


Solution

  • The function passed to filter is not a type guard but you can indicate the type like this:

    constructor(private router: Router) {
      this.routeChange = router.events
        .pipe(
          filter((event): event is NavigationEnd => event instanceof NavigationEnd)
        )
        .subscribe(event => {
          // "event" here is now of type "NavigationEnd"
        });
    }