【Angular】現在開いているページのURLを取得したい

### やりたいこと
- ~~現在開いているページのURLを取得したい~~
- ~~URLに応じてCSSの切り替えや変数の生成を行いたい~~
- （同一router内での）画面遷移後に何かしらのイベントを行いたい

（2022.2.27 追記）これらの用途には不適切な場合もあるなーーと思い1.2個目削除。理由は一番下に記載しました。

### 方法
[公式ドキュメント](https://angular.jp/api/router/RouterEvent)にある通り、`router.events`から`RouterEvent`をsubscribeします。

```typescript:
import { NavigationEnd, RouterEvent, Router } from '@angular/router';

class MyService {
  constructor(private router: Router) {
    this.router.events.pipe(
       filter((e: Event): e is RouterEvent => e instanceof RouterEvent)
    ).subscribe((e: RouterEvent) => {
      // Do something
    });
  }
}
```

すると、コンパイルエラー発生。
>Error: app.component.ts:25:9 - error TS2345: Argument of type 'MonoTypeOperatorFunction<Event>' is not assignable to parameter of type 'OperatorFunction<Event, Event>'.

・・・？？？:thinking:


https://github.com/angular/angular/issues/42920

DOMのEventとrouterのEventは別物だよ！だから`@angular/router`からEventをインポートしてちょ！とのこと。

```typescript:
import { Event,<--追加   NavigationEnd, RouterEvent, Router } from '@angular/router';

class MyService {
  constructor(private router: Router) {
    this.router.events.pipe(
       filter((e: Event): e is RouterEvent => e instanceof NavigationEnd)
    ).subscribe((e: RouterEvent) => {
      // Do something
    });
  }
}
```

よくみると公式のドキュメントのコードでもちゃんと`import { Event, RouterEvent, Router } from '@angular/router';`と記述あります。

```typescript
filter((e: Event): e is RouterEvent => e instanceof RouterEvent)
                   ~~~~~~~~~~~~~~~~    ~~~~~~~~~~~~~~~~~~~~~~~~
```
見慣れないこの辺に気を取られてました。

`is`とか`instanceof`に関してはこの辺が分かりやすそうです。記事書けるほど理解できてないので参考URLだけ。
- 戻り値の型アノテーション

https://typescript-jp.gitbook.io/deep-dive/type-system/functions#rinoanotshon

- `is`

https://qiita.com/ryo2132/items/ce9e13899e45dcfaff9b#is

- `instanceof`

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/instanceof

https://ja.javascript.info/instanceof

### ちなみに

```typescript:
import { Router } from '@angular/router';

class MyService {
  constructor(private router: Router) {
    router.events.subscribe(e => {
      console.log(e)
    });
  }
}
```
のようにするとズラーっとeventが出てくるので、必要な`NavigationEnd`だけfilterしているんですね。
![スクリーンショット 2022-02-26 7.58.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680199/0bd6dcb8-23f4-4ecf-2647-d7b2e3563750.png)


### URLを取得する場合の問題点（2022.2.27追記）
- 現在開いているページのURLを取得したい
- URLに応じてCSSの切り替えや変数の生成を行いたい

という用途には不適切なのでは？と思ったのは、該当`router`（`constructor`内に記術したやつ）の`RouterEvent`が起きずに画面が表示される場合に対応できないため。

例えば
- 画面をリロードした場合
- 検索バーに直接URLを打ち込んで遷移してきた場合
- 親のrouterから遷移してきた場合

上のような場合は該当`router`の`RouterEvent`が起きずURLを取得できない。（この説明で合ってるのかは正直分かりません・・・）


ただし、上のような場合においては

```typescript
this.router.url
```

でURLを取得できます。(ただし、`RouterEvent`は検知できない)
なので併用が良いんじゃないかなあと。僕の今のコードはこんな感じになっております。

```typescript
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Event, NavigationEnd, Router, RouterEvent } from '@angular/router';
// Rxjs
import { Subject } from 'rxjs';
import { filter, takeUntil } from 'rxjs/operators';

@Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.scss'],
})
export class ExampleComponent implements OnInit, OnDestroy {

  private onDestroy$ = new Subject();

  currentUrl:string = '';

  constructor(
    private router: Router
  ) { }

  ngOnInit(): void {
    this.currentUrl = this.router.url;
    this.router.events
      .pipe(
        takeUntil(this.onDestroy$),
        filter((event: Event): event is RouterEvent => event instanceof NavigationEnd),
      ).subscribe((event: RouterEvent) => {
        this.currentUrl = event.url;
      });
  }

  ngOnDestroy(): void {
    this.onDestroy$.next();
  }
}
```