angular: Observable is returning a wrong-sounding 'Event_2' type

Which @angular/* package(s) are the source of the bug?

router

Is this a regression?

No

Description

router.events Observable is returning a ‘Event_2’ type in the API

This seems like an issue with the API Generator. It’s causing autocomplete to hint and add the wrong ‘Event_2’ type to code.

Please provide a link to a minimal reproduction of the bug

https://github.com/angular/angular/blob/master/goldens/public-api/router/router.md

Please provide the exception or error you saw

`readonly events: Observable<Event_2>;`

Please provide the environment you discovered this bug in

No response

Anything else?

No response

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 3
  • Comments: 21 (5 by maintainers)

Most upvoted comments

Thanks @JoostK, you’re right about it being an issue with the autocomplete to try and add add unexported Event_2.

It’s definitely a real issue, because the hinting itself* is going to lend to folks adding Event_2 to their own docs/code comments.

I agree that API Extractor should be smarter here to use the exported type name if available instead of an inaccessible internal type. I’ll open an issue in the API Extractor project.

As a stop gap, is it possible to make the Observable return the Event type? It would be straightforward for every tool’s logic to get it right…

*Insofar as any type hinting logic is concerned, it would not be the prerogative of the tool to resolve internal types to available exported ones, the internal types can be exported multiple times with different names or not at all.

@IvanAmdaris You can drop the map() and use a predicate instead !

const events = this.router.events.pipe(
  filter((event): event is NavigationEnd => event instanceof NavigationEnd),
);

Hi,

I have the same issue. “Event_2” type for “RouterEvent”.

Original code. Screenshot 2023-06-16 at 16 00 06

After removing “RouterEvent”. Screenshot 2023-06-16 at 15 51 10

I’m sharing the workaround that worked for me: the error:

	this.router.events.filter(event => {
			// do something
		       return event instanceof NavigationEnd;
			})

that generates:

Property ‘filter’ does not exist on type 'Observable<Event_2>

Basically wrapping filter function of rxjs inside the pipe function:

	this.router.events.pipe(filter(event => {
		        // do something
			return event instanceof NavigationEnd;
		}))

Version 16

import { NavigationEnd, Router, RouterEvent, Event } from '@angular/router';

this._router.events
.pipe(
  filter((evt: Event | RouterEvent): boolean => {
    return evt instanceof NavigationEnd;
  }),
  take(1)
)
.subscribe((): void => {});

make sure that Event should be imported from ‘@angular/router’;

I was having a similar issue where

import { Event, RouterEvent, NavigationEnd } from '@angular/router';

this.router.events
      .pipe(filter((event: RouterEvent) => event instanceof NavigationEnd))

produced the following error during build:

Error: src/app/_services/config/route-params.service.ts:25:13 - error TS2345: Argument of type 'MonoTypeOperatorFunction<RouterEvent>' is not assignable to parameter of type 'OperatorFunction<Event_2, RouterEvent>'.
  Types of parameters 'source' and 'source' are incompatible.
    Type 'Observable<Event_2>' is not assignable to type 'Observable<RouterEvent>'.
      Type 'Event_2' is not assignable to type 'RouterEvent'.
        Type 'ActivationEnd' is missing the following properties from type 'RouterEvent': id, url

25       .pipe(filter((event: RouterEvent) => event instanceof NavigationEnd))

In the Angular Update Guide, one of the bullet points for updating an app from Angular 15 to 16 is:

  • The Event union no longer contains RouterEvent, which means that if you’re using the Event type you may have to change the type definition from (e: Event) to (e: Event|RouterEvent)

Following this guidance, I changed the line from

.pipe(filter((event: RouterEvent) => event instanceof NavigationEnd))

to

.pipe(filter((event: Event|RouterEvent) => event instanceof NavigationEnd))

and this resolved the issue for me.

Just my two cents about this issue, the Event type is part of the router package and furthermore it could be possible you need also a type guard to be able to use that event later.

import { Event, RouterEvent, NavigationEnd } from '@angular/router';

this.router.events.pipe(
  filter(
    (event: RouterEvent): event is NavigationEnd => event instanceof NavigationEnd)
  ),
  map(event: NavigationEnd) => ...

Nothing in here was working for me, here is what I had to use - kind of odd router.events if of type Event_2 I even updated angular/core to ^16.2.1 today to confirm this wasn’t some regression from v16.x.x that was already fixed

        this.router.events.pipe(
            map((event: any) => event.routerEvent as RouterEvent),
            filter((event): event is NavigationEnd => event instanceof NavigationEnd)
        );

This one worked for me but I haven’t tested yet. Sorry for not sharing.

Screenshot 2023-06-26 at 13 44 33

Thanks for replying so fast, nice to see people do that here, I tried that and it seems to be working.

What also seems to be working is just use Event instead of Event_2 the only thing that I haven’t noticed was that when writing Event the auto import wouldn’t trigger for me so if you find yourself in my situation make sure to import { Event } from '@angular/router';

This one worked for me but I haven’t tested yet. Sorry for not sharing.

Screenshot 2023-06-26 at 13 44 33

Hi ,

I am getting the same issues with the Event_2 type for RouterEvent. How could we possibly fix it?

this.router.events.pipe(
      filter((e:Event): e is RouterEvent => e instanceof RouterEvent)).subscribe(
        (e:RouterEvent)=>{

        })
    )