はじめに
前回
TypeScriptにおける「型の安全性」の議論で、必ず登場するキーワードが any と unknown である。
初心者にとっては、エラー回避のために any を使うことが簡単に見えるが、
これは長期的に見ると非常に危険である。今回は、
-
anyが持つ“便利さ”と“危うさ” -
unknownの正しい使い方 - 安全な型ガードの実装
について、具体的なコード例を交えながら解説する。
any:TypeScriptの“穴”
まずは any の性質を見てみよう。
let value: any = "hello";
value.toUpperCase(); // OK
value(); // 実行時エラー(でもコンパイルは通る)
特徴:
- どんな値でも代入できる
- どんな操作でもコンパイルエラーが出ない
- 型安全性を完全に無視
つまり、TypeScriptを導入した意味が根底から失われてしまうのである。
unknown:厳格な any
次に、unknown を見てみよう。
let value: unknown = "hello";
value.toUpperCase(); // ❌ エラー
if (typeof value === "string") {
console.log(value.toUpperCase()); // ✅ 型ガードが効く
}
特徴:
- どんな値でも代入できる(
anyと同様) - ただし利用には“型ガード”が必須
- 安全性と柔軟性のバランスが取れている
anyを使う場面はあるのか?
結論から言えば、“最小限に限る”である。以下のような場面では any を使う合理性がある:
- レガシーコードやライブラリとの互換性確保
- 一時的なプロトタイプ開発(後で修正する前提)
- TypeScript未対応の外部モジュールとの橋渡し
ただし、どの場合でも コメントで any の理由を書く ことを徹底すべきである。
// 仕方なく any を使用:この外部APIのレスポンス型が不定なため
const response: any = await fetch(url);
unknownの活用例
例えば、フォームからの入力値や、JSON.parse の戻り値に対して unknown を使うのが定石である。
function handleInput(input: unknown) {
if (typeof input === "string") {
console.log("String length:", input.length);
} else if (typeof input === "number") {
console.log("Rounded:", Math.round(input));
} else {
console.log("Unsupported type");
}
}
このようにすれば、実行時エラーのリスクを排除しつつ、柔軟に対応できる。
まとめ
| 比較項目 | any | unknown |
|---|---|---|
| 代入可能 | ○ | ○ |
| 操作制限 | 無制限 | 型ガード必須 |
| 安全性 | 低い | 高い |
| 推奨度 | ✕(原則非推奨) | ◎(安全な汎用型) |
any を“便利だから”で使ってしまうと、コード全体の保守性が著しく低下する。
一方 unknown は、堅牢なコードを書くための「型安全な柔軟性」を提供する。
TypeScriptの真価は「型を活かした堅牢な設計」である。
その恩恵を最大化するには、“型の選択”こそが最重要なのである。
次回は「型定義を極める:型エイリアス・インターフェース・交差型のすべて」をテーマに、TypeScriptにおける型の設計力を高めていく。