【TypeScript】anyはなぜ危険?unknownとの違いと使い分けを整理する
TypeScriptを書いていると、anyって便利だけどなんか怖い…という感覚、ありませんか?
この記事では、anyとunknownの本質的な違いを整理したうえで、「どちらをどんな場面で使うか」の判断基準まで説明します。
この記事は次のような方におすすめです。
- TypeScriptでanyを使ったことはあるが、「本当にこれでいいのか」と不安を感じている方
- anyとunknownの違いがなんとなくしかわからない方
- unknownを使うべきと聞いたが、具体的な書き方がわからない方
- プリミティブ型や型推論はひととおり学んだ、TypeScript初心者の方
この記事を読むと、anyとunknownの使い分けの基準がつかめて、「なんとなくanyを使う」状態から抜け出せます。
それでは、順を追って詳しく見ていきましょう!
- 未経験で後悔したくない
【実体験】未経験からITエンジニアに転職して後悔した話|4社経験してわかった「最初の選択ミス」 - 年収が低くて不安
4年間ずっと年収260万だったエンジニアが、転職で510万になるまでの全記録
anyとunknownはどちらも「何でも受け取れる型」
まず、anyとunknownには共通点があります。どちらも、どんな値でも代入できる型です。
let a: any;
a = 42; // OK
a = "こんにちは"; // OK
a = true; // OK
let b: unknown;
b = 42; // OK
b = "こんにちは"; // OK
b = true; // OK
どちらも代入の段階ではエラーになりません。
「じゃあ同じじゃないの?」と思うかもしれませんが、違いが出るのは「代入した後、その値を使おうとした瞬間」です。ここが、この2つの型の本質的な分かれ目になります。
anyとunknownの本質的な違い — 型チェックが効くかどうか
anyを使うと、型チェックが無効になる
anyを使うと、TypeScriptの型チェック機能が実質的にオフになります。どんな操作をしようとしてもエラーが出ません。
let value: any = "こんにちは";
// 文字列っぽく使っても…
console.log(value.toUpperCase()); // OK(TypeScriptはエラーを出さない)
// 数値っぽく使っても…
console.log(value.toFixed(2)); // OK(TypeScriptはエラーを出さない)
「エラーが出ないならいいじゃないか」と思うかもしれません。でも、上のコードでvalue.toFixed(2)を実行すると、実行時にエラーになります。文字列にはtoFixedというメソッドがないからです。
anyの問題は「コンパイル時にエラーを検知できない」こと。TypeScriptを使っているのに、JavaScriptのときと同じ状態に戻ってしまうイメージです。
unknownは型チェックを保ったまま受け取れる
一方、unknownを使うと「受け取りはするけど、使うには確認が必要」という動作になります。
let value: unknown = "こんにちは";
// そのまま使おうとするとエラーになる
console.log(value.toUpperCase()); // エラー:'value' is of type 'unknown'
「使えないなら意味ないじゃないか」と思うかもしれませんが、これは意図的な設計です。unknownは「型が不確かな値は、確認してから使ってください」とTypeScriptが要求している状態です。
unknownを実際に使うには「型の絞り込み」が必要
unknownの値を使うには、「この値はこういう型ですよ」とTypeScriptに教えてあげる必要があります。これを型の絞り込みと呼びます。
typeofで絞り込む
最もよく使う方法が、typeof演算子を使った絞り込みです。
function printValue(value: unknown) {
if (typeof value === "string") {
// この中ではvalueはstring型として扱える
console.log(value.toUpperCase()); // OK
} else if (typeof value === "number") {
// この中ではvalueはnumber型として扱える
console.log(value.toFixed(2)); // OK
}
}
typeof value === "string" というチェックを通過した後は、TypeScriptがvalueをstring型だと認識してくれます。このように「条件で絞り込むことで型を確定させる」仕組みを型ガードと言います。
instanceofで絞り込む
オブジェクトやクラスのインスタンスを確認したい場合はinstanceofを使います。
function handleError(error: unknown) {
if (error instanceof Error) {
// この中ではerrorはError型として扱える
console.log(error.message); // OK
}
}
try-catchのcatch節でエラーを受け取るときによく使うパターンです。
型アサーション(as)で絞り込む場合の注意点
「絞り込みが面倒だから、asで強制的に型を指定すればいいのでは?」と思う方もいるかもしれません。
let value: unknown = "こんにちは";
const str = value as string; // TypeScriptはエラーを出さない
console.log(str.toUpperCase()); // OK
これは動きますが、asは型チェックをスキップするため、使い方を誤ると実行時エラーの原因になります。
let value: unknown = 42;
const str = value as string; // 本当は数値なのに…
console.log(str.toUpperCase()); // 実行時エラー!
asを使うのは「自分が型を確実に把握している場面」に限定するのが安全です。typeof/instanceofによる絞り込みを先に検討するようにしましょう。
anyとunknownの違いを表で整理する
ここまでの内容をまとめます。
| 比較項目 | any | unknown |
|---|---|---|
| 何でも代入できるか | ✅ できる | ✅ できる |
| 型チェックが効くか | ❌ 効かない | ✅ 効く |
| そのまま操作できるか | ✅ できる(危険) | ❌ 絞り込みが必要 |
| TypeScriptの恩恵を受けられるか | ❌ 受けられない | ✅ 受けられる |
| 安全性 | 低い | 高い |
一言でまとめると、「型が不確かな値を受け取りたいときは、anyよりunknownを使う方がTypeScriptらしい書き方」です。
anyをいつ使っていいのか — やむを得ない場面を整理する
「anyはダメ」とよく言われますが、現実のコードではanyが出てくる場面もあります。すべてがNG というわけではなく、「やむを得ない場面」を知っておくことが大切です。
anyを使ってもよいと判断できる代表的な場面は以下の通りです。
既存のJSコードを段階的にTS化しているときに、一時的にanyを使うことがあります。「まずコンパイルを通す、型は後から整える」という移行戦略の一環として許容されます。
外部ライブラリの中には、TypeScriptの型定義(.d.tsファイル)が提供されていないものがあります。この場合、一時的にanyで受け取ることがあります。
型定義が複雑すぎる場面で、あえてanyを使ってシンプルにするケースもあります。ただし、この判断はTypeScriptへの理解が深まってから行うものです。
開発中は、「anyを使いたくなったら、まずunknownで代替できないか考える」習慣をつけておくと、TypeScriptの恩恵をより受けやすくなります。
【付録】さらに学びを深めるためのリソース
さらにTypescriptの学習を進めたい方のために、いくつかのリソースを紹介します。
これらのリソースを活用することで、TypeScriptの型システムについてより深い知識を得ることができるでしょう。
おすすめの書籍
ゼロからわかる TypeScript入門
技術評論社から出版されている「ゼロからわかる TypeScript入門」は、プログラミング初心者や本職プログラマーではない方を主な対象にした入門書です。
変数・条件分岐・ループといった基本から、クラスやインターフェース、モジュールまで段階的に学べる構成になっています。最終章ではWeb APIとJSONを使った非同期Webアプリの作成も体験できるので、「実際に動くものを作る」ところまで到達できます。
プロを目指す人のためのTypeScript入門
技術評論社の「プロを目指す人のためのTypeScript入門 安全なコードの書き方から高度な型の使い方まで」、通称 ブルーベリー本 です。
JavaScriptの仕様とTypeScript独自の機能を両方押さえつつ、リテラル型・ユニオン型・keyof型・ジェネリクスなど、高度な型表現まで踏み込んで解説しています。TypeScriptの型システムの表現力を本格的に学べる一冊です。
オンラインで参照できる公式ドキュメント
TypeScript公式ハンドブック
https://www.typescriptlang.org/docs/
TypeScriptの公式ドキュメントです。
intersection型を含む、すべての型システムの機能について詳細な説明があります。
TypeScript Deep Dive
https://basarat.gitbook.io/typescript/
TypeScriptの深い部分まで掘り下げて解説しているオンラインブックです。
無料で読むことができ、intersection型についても詳しく説明されています。
TypeScriptの学習は終わりがありません。
新しい機能が常に追加され、より良い書き方が発見されています。
継続的に学習を続けることで、より良いTypeScriptプログラマーになれるはずです。
まとめ:迷ったらunknownから始めよう
この記事で押さえてほしいポイントを整理します。
- anyとunknownはどちらも「何でも代入できる型」という点では同じ
- 違いは「型チェックが効くかどうか」。anyは型チェックが無効になり、unknownは保たれる
- unknownを使うには
typeofやinstanceofによる型の絞り込みが必要 as(型アサーション)は絞り込みの代替になるが、誤用すると実行時エラーの原因になるため注意- anyが必要になる場面はあるが、まずunknownで代替できないかを考えるのが基本
型が不確かな値を受け取りたいとき、最初にunknownを使うことを習慣にするだけで、TypeScriptの安全性が格段に高まります。
※本記事の本文案はAIを活用して作成していますが、記載している内容およびコードは筆者が実際に調査、検証・実行し、内容の正確性を確認した上で公開しています。




