← Angular コース
46. toSignal と toObservable — 2つの世界の橋渡し
Angularには「時間とともに届く値」を扱うRxJSの世界と、「今の値」を扱うシグナルの世界があります。@angular/core/rxjs-interop の toSignal と toObservable は、この2つを行き来する橋です。toSignal(obs$) はObservableをシグナルに変換し、値が届くたびにシグナルが更新されます。逆に toObservable(sig) はシグナルの変化をObservableの流れとして取り出します。
実務でよく使うのは、HttpClientが返すObservableを toSignal でシグナルにする形です。テンプレートでは users() と普通のシグナルとして読むだけでよく、asyncパイプもsubscribeも不要になります。逆方向の toObservable は、検索語のシグナルを流れに変えて switchMap につなぐなど、「シグナルの変化をきっかけに通信したい」場面で活躍します。
つまずきやすいのは初期値です。Observableは最初の値が届くまで何も持たないため、toSignal(obs$, { initialValue: [] }) のように initialValue を指定しないと、シグナルの型に undefined が混ざります。テンプレートで配列として扱うなら空配列を初期値にしておくのが定番です。また、toSignal は購読の解除を自動で行うため、コンポーネントのフィールド初期化などDIコンテキストの中で呼ぶ必要があります。
サンプルコード(フレームワーク環境が必要なため表示のみ)
import { Component, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { toSignal } from '@angular/core/rxjs-interop';
type User = { id: number; name: string };
@Component({
selector: 'app-user-list',
// シグナルなので users() と呼び出すだけ。async パイプも不要
template: '@for (user of users(); track user.id) { <p>{{ user.name }}</p> }',
})
export class UserListComponent {
private http = inject(HttpClient);
// Observable をシグナルに変換。届くまでは initialValue の空配列
users = toSignal(this.http.get<User[]>('/api/users'), {
initialValue: [] as User[],
});
}
サンプルコードで身につける(5本) →
学んだ概念を、素朴な例から実務寄りの例まで5つの具体例で確認します。
公式ドキュメントで詳しく ↗