any型とunknown型は「似て非なるもの」
どちらも「どんな値でも代入できる型」ですが、性格は真逆です。
ざっくり言うと、
- any型:型チェックをほぼ無効化する「なんでもアリモード」
- unknown型:何でも受け取るけれど「使う前に必ずチェックさせる安全モード」
どちらも「受け取る側」としては柔軟ですが、「使う側」としての厳しさがまったく違います。
any型の振る舞いと問題点
何でも代入できて、どこにでも代入できる
let value: any;
value = 123;
value = "hello";
value = { a: 1 };
let num: number = value; // OK
let str: string = value; // OK
TypeScriptany は「どんな型の値も受け取れる」うえに、「その値をどんな型の変数にも代入できる」型です。
つまり、TypeScriptの型チェックをほぼスキップしてしまいます。
メソッド呼び出しも全部通ってしまう
let value: any = "hello";
value.toUpperCase(); // OK(コンパイルは通る)
value.nonExist(); // これもコンパイルは通る(実行時に落ちる可能性)
TypeScriptany に対しては、存在しないプロパティやメソッドを呼んでもコンパイルエラーになりません。
「コンパイル時に守ってくれるはずのもの」が、ほぼ全部オフになるイメージです。
unknown型の振る舞いと特徴
「何でも受け取る」が「そのままでは使えない」
let value: unknown;
value = 123;
value = "hello";
value = { a: 1 };
let num: number = value; // エラー
TypeScriptunknown も「どんな値でも代入できる」点では any と同じです。
ただし、unknown をそのまま他の型に代入したり、メソッドを呼んだりすることはできません。
let value: unknown = "hello";
// value.toUpperCase(); // エラー: 'value' is of type 'unknown'
TypeScriptコンパイラは「中身が何か分からないから、勝手に触るな」と止めてくれます。
型ガードで「安全を証明」すれば使える
let value: unknown = "hello";
if (typeof value === "string") {
value.toUpperCase(); // OK(このブロック内では string とみなされる)
}
TypeScriptunknown は、「使う前に型チェック(絞り込み)をしなさい」ということを強制する型です。
この「チェックを強制する」という点が、anyとの決定的な違いです。
any型とunknown型の決定的な違い
「自由度」と「安全性」のトレードオフ
よく整理された比較として、こんな関係があります。
- any
- どんな値でも代入できる
- どんな型の変数にも代入できる
- どんな操作も許される(メソッド呼び出しなど)
- 型安全性は低い(型チェックを回避)
- unknown
- どんな値でも代入できる
- そのまま他の型に代入できない
- そのままメソッドを呼べない
- 型チェック(絞り込み)を強制するので型安全性が高い
同じ「何でも受け取れる」でも、
any は「何でもできるけど、何も守ってくれない」
unknown は「何でも受け取るけど、勝手なことはさせない」
という真逆の性格を持っています。
実際のコードでの違いを並べて見る
代入の違い
let a: any = "hello";
let u: unknown = "hello";
let s1: string = a; // OK
// let s2: string = u; // エラー: 'unknown' を 'string' に割り当てられない
TypeScriptany はどこにでも流し込めますが、unknown は「ちゃんと中身を確認してからにして」と止めてくれます。
メソッド呼び出しの違い
let a: any = "hello";
let u: unknown = "hello";
a.toUpperCase(); // OK(コンパイルは通る)
// u.toUpperCase(); // エラー: 'u' is of type 'unknown'
TypeScriptunknown は、「本当に string だと分かるまでは toUpperCase を呼ばせない」というスタンスです。
初心者が身につけたい「使い分けの感覚」
デフォルトで選ぶべきは unknown
「どんな値が来るか分からない」状況で、
・型安全性を捨ててもいいから、とにかく動かしたい → any
・型安全性は守りたい。面倒でもチェックしてから使いたい → unknown
という選択になります。
TypeScriptの目的を考えると、基本的には unknown を選ぶ方が健全です。
any は「型安全性を捨てる代わりに自由を得る」最後の手段としてだけ使う、くらいの感覚でちょうどいいです。
具体的な指針(ざっくり)
外部から来るデータ(APIレスポンス、JSONパース結果など)
→ まず unknown で受けて、型ガードやバリデーションで絞り込む
古いコードや型定義のないライブラリを一時的に動かしたい
→ やむを得ず any を使うことはあるが、範囲を小さく閉じ込める
「とりあえずエラーを消したいから any」
→ 一番危険なパターン。unknown か、ちゃんとした型定義を検討するべき
まとめ:anyは「型チェックOFF」、unknownは「型チェックONのまま不明」
最後に一番大事なイメージだけ残すと、こうです。
any:
「この値について、TypeScript は何も文句を言わないで」
→ 型チェックOFF、守りゼロ
unknown:
「この値が何かは分からないけど、勝手に触らせないで」
→ 型チェックONのまま、「使う前に必ず確認させる」
「分からないもの」を扱うときに、
安全側に倒したいなら unknown、
安全性を犠牲にしてでも突っ走りたいなら any。
あなたがこれからTypeScriptを「長く気持ちよく」使っていきたいなら、
迷ったときの合言葉は、
「分からないものは unknown、どうしても必要なときだけ any」。
ここを軸にしておくと、型の世界で迷子になりにくくなります。

