x is T カスタム型ガードとアサーション関数
最終更新:2026-10-22
x is T カスタム型ガードとアサーション関数
組み込みガード(typeof/instanceof/in)で足りないときは、自分で型ガード関数を書けます。戻り値を x is T(型述語)とすれば、関数が true を返した分岐内で TS は x を T へナローイングます。その兄弟分がアサーション関数(asserts x is T)で、boolean を返す代わりに失敗時に例外を投げます。
| グループ | ナローイングとアサーション |
|---|---|
| 種類 | 構文 |
| strict モード | 不要 |
ℹ️ 説明 エディタは TypeScript を JavaScript にトランスパイルして実行します(型チェックなし)。型チェック結果は各サンプルの出力を参照してください。
📝 構文
// 型述語:true を返す箇所では x は T にナローイングされる
function isFoo(x: unknown): x is Foo {
return typeof x === "object" && x !== null && "foo" in x;
}
// アサーション関数:不正なら例外を投げ、通過後は x を T として扱う
function assertFoo(x: unknown): asserts x is Foo {
if (!isFoo(x)) throw new Error("not a Foo");
}
⚙️ パラメータ
| x is T | 型述語の戻り値型です。パラメータ名 is 目標型。関数の本体では実際の実行時チェックを行う必要があります |
|---|---|
| asserts x is T | アサーション関数の戻り値型です。検証に失敗したら例外を投げるべきで、呼び出し後のコードは x を T として扱います |
戻り値:is 述語関数は実行時には普通の boolean 関数で、ナローイング効果はコンパイル時に起こります。asserts 関数は実行時の戻り値がなく(void)、失敗は throw で伝えます。
▶ サンプル
下のコードを編集して「試す」を押すと、トランスパイル実行結果を確認できます:
出力:
failed: 404
data: x,y
(トランスパイル後の実行出力。isFailure が true を返すと res は ApiError に絞り込まれ、res.data が型チェックを通ります。ナローイングは tsc が静的に保証し、実行時に見えるのは値だけです)
💡 ポイント
ℹ️ 説明 x is T はコンパイラの見方を変えるだけです。実行時には普通の関数にすぎません。本体のチェックは宣言した T と一致していなければならず、さもなければコンパイラに嘘をつくことになります。
⚠️ 注意 ガードを間違えてもコンパイラは気づきません。たとえば res is ApiError と宣言しながら関係のないフィールドをチェックすれば、誤った型が静かに分岐へ流れ込み、実行時に爆発します。ガードのロジックはテストしましょう。
💡 ヒント パラメータの型は any ではなく unknown にしましょう。unknown はナローイングしない限り操作できないため、完全な検証ロジックを書くことを強制できます。
🏷️ 関連ナローイングとアサーション
💡 関連ケース
ケースは今後追加予定です。
📚 関連チュートリアル
❓ よくある質問
Q x is T と単に boolean を返すのは何が違いますか?
A boolean を返すだけでは、true が何を意味するのかコンパイラに分からず、呼び出し後も x の型は変わりません。x is T を返せば、true の分岐内で x が T へ絞り込まれます。述語は型だけの変更で、実行時のオーバーヘッドはゼロです。
Q いつ is 版ではなく asserts 版を使うべきですか?
A データが不正なら即座に終了すべき場面(設定の読み込み、テストのアサーション、環境の検証)では asserts x is T を使いましょう。失敗時に例外を投げ、以降のコードは安心して使えます。「どちらかの分岐」で処理したい(成功なら A、失敗なら B)場合は is を使います。
Q TS 4.4 以降、もっと手軽な書き方はありますか?
A あります。TS 4.4 からは const isFailure = res.ok === false のような boolean 値でも自動的にナローイングが効き(aliased conditions)、const に束ねた判定を間接的に再利用できます。ただし、名前付きのガード関数にまとめるのが再利用性の高いやり方です。