型アサーションと型ガード
05章で学んだNarrowingは、TypeScriptが制御フローから自動的に型を絞り込む仕組みでした。この章では、開発者が明示的に型を指定する手法を扱います。
学習者コンパイラが「型が違う」って怒るとき、とりあえず as で黙らせちゃダメなの…?
型アサーション(as)
型アサーションは、TypeScriptの型推論結果を開発者が上書きする手段です。
どういう時に使用するか
具体的な使用シーンは主に以下の3つです。
| 使用シーン | 説明 |
|---|---|
| DOM要素を取得する時 | document.getElementById('my-input') などで要素を取得すると、TypeScriptはそれを単なる「一般的なHTML要素」としか認識しません。HTMLInputElement など具体型に断言することで、.value など要素固有のプロパティがエラーにならずに使えます。 |
| 外部データ(APIのレスポンスなど)を受け取る時 | JSON.parse() の結果など、外部から来たデータは中身がわからないため any や unknown 型になります。「このデータは User 型だ」と断言して、プログラム内で扱いやすくします。 |
| イベントハンドラの引数を使う時 | クリック時などの event.target は抽象的な型になっているため、ボタンやリンクなど具体的なHTML要素の型に断言して操作します。 |
型アサーションは「コンパイラの安全装置をオフにして無理やり通す」行為です。そのため、本当にその型である確証がある時だけ使う(乱用しない)のが鉄則です。
型アノテーションと型アサーションの違い
型アノテーション と 型アサーション は、
-
型アノテーション『注釈』
変数や関数を定義する際に、「これにはこの型のデータが入る」と最初から明示的に指定するもの
-
型アサーション『断定』
コンパイラが自動で推論した型に対して、プログラマが「いいや、これはこの型として扱え」と強制的に上書きするものです
どちらも型を指定する役割を持ちますが、使われる目的やタイミングに違いがあります。
型アサーションと型キャストの違い
型キャスト は別の型に変換する手段です。
一方、型アサーション はデータそのものは一切変更しません。TypeScriptのコンパイラに対する「見せ方(認識)」だけを変えます。
下記は型キャストの例
const n = 123; // nは数値(Number)
const s = String(n); // sは文字列(String)の "123" に変換される非nullアサーション(!)
非nullアサーションは、変数の後ろに ! を付けることで「この値は null や undefined ではない」とコンパイラに断言する記法です。
値が null または undefined になりうる型(例:string | null)に対して、開発者が「ここでは絶対に値が存在する」と保証することで、null チェックなしでプロパティやメソッドにアクセスできるようになります。
function getLength(text: string | null) {
// ① text は null の可能性があるため、そのまま .length にアクセスするとエラー
// console.log(text.length); // ❌ 'text' is possibly 'null'.
// ② ! を付けて「null ではない」と断言すると、エラーにならずアクセスできる
console.log(text!.length);
}よく使われるのは、DOM要素の取得結果のように「存在するはずだが、型の上では null の可能性が残る」ケースです。
// getElementById の戻り値は HTMLElement | null
const button = document.getElementById('submit')!;
// ! を付けることで HTMLElement として扱える
button.addEventListener('click', () => {});そのため、可能な限り ! ではなく、より安全な代替手段を優先します。
| 手段 | 例 | 特徴 |
|---|---|---|
| オプショナルチェーン(?.) | text?.length | null / undefined なら処理を中断し undefined を返す |
| Null合体演算子(??) | text ?? '初期値' | null / undefined のときに既定値を使う |
| 型ガード(if文によるチェック) | if (text !== null) { ... } | 実行時に確認するため最も安全 |
! は「他に手段がなく、かつ値が存在することが確実に分かっている」場合の最後の手段として使うのが鉄則です。
型ガードで型安全を保証する
型ガード(Type Guard)とは、 プログラムの実行時にデータの中身をチェックすることで、TypeScriptの型を安全に絞り込む仕組みです。
function printValue(value: string | number) {
// ① この時点では string か number か分からないため、文字列専用の value.length はエラーになる
if (typeof value === 'string') {
// ② 型ガードが働き、このブロック内では確実に「string(文字列)」として認識される!
console.log(value.length); // エラーにならない
} else {
// ③ ここでは自動的に残りの「number(数値)」として認識される
console.log(value * 10);
}
}ユーザー定義型ガード(is)
function isUser(value: unknown): value is User {
return typeof value === 'object' && value !== null && 'name' in value;
}is キーワードを使って、関数の戻り値で型を絞り込む手法。APIレスポンスのバリデーションなどで活用するパターンを解説予定です。
constアサーション
const config = {
endpoint: '/api/users',
method: 'GET',
} as const;
// { readonly endpoint: "/api/users"; readonly method: "GET" }オブジェクトや配列をリテラル型として固定する as const の使い方を解説予定です。
型アサーション vs 型ガード — どちらを使うべきか
安全性の観点からの使い分けを解説予定です。
この章の詳細な内容は順次追加していきます。