Angular Error TS2345: Argument of type 'MonoTypeOperatorFunction<Event>' is not assignable to parameter of type 'OperatorFunction<Event, Event>'

Viewed 2956

Trying to troubleshoot this code,

import { Event, Router, RoutesRecognized, ActivationStart, NavigationEnd } from "@angular/router";

...

this._router.events.pipe(
    filter((evt: Event) => evt instanceof RoutesRecognized),
    map((evt: RoutesRecognized) => evt.state.root),
).subscribe((rootRoute: ActivatedRouteSnapshot) => (
    this._resolvedRoutes = this._getResolvedRoutes(rootRoute.children)
));

Which is producing this error,

ERROR: projects/acme/angular-ui/src/lib/services/breadcrumb/breadcrumb.service.ts:213:11 - error TS2345: Argument of type 'MonoTypeOperatorFunction<Event>' is not assignable to parameter of type 'OperatorFunction<Event, Event>'.
  Types of parameters 'source' and 'source' are incompatible.

What exactly is the problem here? I'm guessing the MonoTypeOperatorFunction<Event> function is the filter, but I have no idea what the OperatorFunction<Event, Event> why would there be two type-variables in the map? How do I resolve this?

2 Answers

Use a user-defined type-guard

I tried this previously, but this is the format you'll want:

this._router.events.pipe(
    filter((evt: Event): evt is RoutesRecognized => evt instanceof RoutesRecognized),
    map((evt: RoutesRecognized) => evt.state.root),
).subscribe((rootRoute: ActivatedRouteSnapshot) => (
    this._resolvedRoutes = this._getResolvedRoutes(rootRoute.children)
));

Now in my case, that produces this error:

ERROR: projects/acmeco/angular-ui/src/lib/services/breadcrumb/breadcrumb.service.ts:213:11 - error TS2345: Argument of type 'import("/home/ecarroll/code/js/myworkspace/projects/acmeco/angular-ui/node_modules/rxjs/internal/types").OperatorFunction<import("/home/ecarroll/code/js/myworkspace/node_modules/@angular/router/router").Event, import("/home/ecarroll/code/js/myworkspace/node_modules/@angular/router/router").RoutesRecognized>' is not assignable to parameter of type 'import("/home/ecarroll/code/js/myworkspace/node_modules/rxjs/internal/types").OperatorFunction<import("/home/ecarroll/code/js/myworkspace/node_modules/@angular/router/router").Event, import("/home/ecarroll/code/js/myworkspace/node_modules/@angular/router/router").RoutesRecognized>'.
  Types of parameters 'source' and 'source' are incompatible.
    Type 'import("/home/ecarroll/code/js/myworkspace/node_modules/rxjs/internal/Observable").Observable<import("/home/ecarroll/code/js/myworkspace/node_modules/@angular/router/router").Event>' is not assignable to type 'import("/home/ecarroll/code/js/myworkspace/projects/acmeco/angular-ui/node_modules/rxjs/internal/Observable").Observable<import("/home/ecarroll/code/js/myworkspace/node_modules/@angular/router/router").Event>'.
      The types of 'source.operator.call' are incompatible between these types.
        Type '(subscriber: import("/home/ecarroll/code/js/myworkspace/node_modules/rxjs/internal/Subscriber").Subscriber<any>, source: any) => import("/home/ecarroll/code/js/myworkspace/node_modules/rxjs/internal/types").TeardownLogic' is not assignable to type '(subscriber: import("/home/ecarroll/code/js/myworkspace/projects/acmeco/angular-ui/node_modules/rxjs/internal/Subscriber").Subscriber<any>, source: any) => import("/home/ecarroll/code/js/myworkspace/projects/acmeco/angular-ui/node_modules/rxjs/internal/types").TeardownLogic'.
          Types of parameters 'subscriber' and 'subscriber' are incompatible.
            Type 'import("/home/ecarroll/code/js/myworkspace/projects/acmeco/angular-ui/node_modules/rxjs/internal/Subscriber").Subscriber<any>' is not assignable to type 'import("/home/ecarroll/code/js/myworkspace/node_modules/rxjs/internal/Subscriber").Subscriber<any>'.
              Property 'isStopped' is protected but type 'Subscriber<T>' is not a class derived from 'Subscriber<T>'.

This error is because TypeScript is unsound, and you have two similarly named types. You can get more information about the conflict with npm list rxjs. You can fix this problem following this blog post,

By adding to your tsconfig.json

"paths": {
    "rxjs": [
      "node_modules/rxjs"
    ],
    "rxjs/*": [
      "node_modules/rxjs/*"
    ]
}

This will force all of your versions to use the same version of rxjs.

I had similar situation while writing an interceptor.

export class MyInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler) {
    return next.handle(req).pipe(
      filter(event => event instanceof HttpResponse),
      map((event: HttpResponse<any>) => {
        // clone event and do stuff
        return event;
      })
    );
  }
}

On 'filter' I got the following error:

Type 'Observable<HttpEvent>' is not assignable to type 'Observable<HttpResponse>'.

The solution with "paths" in tsconfig.json didn't help, so I just worked it around by writing it the following way:

export class MyInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler) {
    return next.handle(req).pipe(
      map(event => {
        if (event instanceof HttpResponse) {
          // clone event and do stuff
        }
        return event;
      })
    );
  }
}

Works like a charm. :)

Related