【実務・中級編】 anyとunknownの比較とベストプラクティス – TypeScript実践ガイド

やあ、今日もコードと格闘しているかな。

フロントエンドの現場でTypeScriptを触っていると、必ずと言っていいほどぶち当たる壁がある。それが「型がわからないとき、どうするか」という問題だ。APIからのレスポンス、レガシーコードからの泥水のようなデータ……そんな時、つい甘い誘惑に負けて `any` を書いてしまったことはないか?

今日は、その「甘い誘惑」がいかに危険で、なぜ我々プロフェッショナルが `unknown` を選ぶべきなのか、その哲学と実戦的なテクニックを共有しようと思う。

—

1. `any` という名の「思考停止」

`any` はTypeScriptにおける「型安全の放棄」だ。これを使うと、コンパイラは君のコードを監視するのをやめる。

// 悪い例: anyを使うとチェックが効かない
const data: any = JSON.parse(‘{“name”: “Alice”}’);

// コンパイラは何も言わないが、実行時にクラッシュする可能性がある
console.log(data.profile.age); // 実行時エラー: Cannot read property ‘age’ of undefined

`any` を使うということは、「私はこのデータの構造を理解する努力を放棄しました」と宣言しているに等しい。そして、そのツケは数ヶ月後の自分や、コードを引き継いだ同僚が、深夜のデバッグで払うことになる。ブラウザの実行環境(V8エンジンなど)は、`any` が何を指しているかなんて全く気にしない。だからこそ、TypeScriptの層で食い止める必要があるんだ。

2. `unknown` は「安全な入り口」

そこで登場するのが `unknown` だ。これは「現時点では型が不明だが、扱う前に必ず型を確認しなければならない」という、TypeScriptからの強い警告だ。

`any` と `unknown` の最大の違いは、「型チェックを強制するか否か」に尽きる。

// unknownで受けることで、安全性を担保する
const rawData: unknown = JSON.parse(‘{“name”: “Alice”}’);

// ❌ エラー: オブジェクトの型が不明なままアクセスすることはできない
// console.log(rawData.name);

// ✅ これが本来あるべき姿(タイプガード)
if (typeof rawData === ‘object’ && rawData !== null && ‘name’ in rawData) {
console.log((rawData as { name: string }).name);
}

`unknown` は「なんでも入る箱」ではなく、「中身を確認するまで開けてはいけない金庫」だと考えてほしい。

3. 実践:型アサーションとユーザー定義型ガード

実務では、いちいち `typeof` を書くのが面倒になることもあるだろう。そんな時は、「型述語(Type Predicates)」を自作して、型を絞り込むのがシニアの流儀だ。

以下は、APIレスポンスを安全にパースするための、現場でそのまま使えるパターンだ。

// ユーザー型定義
interface User {
id: number;
name: string;
}

// ユーザー定義型ガード関数
// この関数を通すことで、unknownからUserへと安全に変換できる
function isUser(data: unknown): data is User {
return (
typeof data === ‘object’ &&
data !== null &&
‘id’ in data && typeof (data as any).id === ‘number’ &&
‘name’ in data && typeof (data as any).name === ‘string’
);
}

// APIからのレスポンスを想定
const response: unknown = { id: 1, name: ‘Tanaka’ };

if (isUser(response)) {
// ここでは型が User に絞り込まれている
console.log(`User name is: ${response.name}`);
} else {
console.error(“想定外のレスポンスフォーマットです”);
}

4. なぜ `unknown` を優先すべきなのか?

結論から言えば、「実行時の予期せぬエラーを、開発時のコンパイルエラーとして早期発見するため」だ。

  • 保守性: `any` が混ざると、IDEの自動補完が効かなくなり、リファクタリングが地獄と化す。
  • 信頼性: `unknown` を使えば、データが壊れていた際に「どこで型チェックを忘れたか」が明確になる。
  • ドキュメント化: `unknown` は、コード自体が「このデータは外部からの入力である」という重要なドキュメントになる。

最後に:先輩からのアドバイス

「急いでいる時ほど、`any` を書きそうになる」。それは痛いほどわかる。しかし、TypeScriptの恩恵を最大限に引き出すためには、「境界線(Boundary)」で必ず型を付ける意識を持つことだ。

APIレスポンスの受け取り口、外部ライブラリとの接点。そこだけ `unknown` から型安全な型へと変換してしまえば、アプリケーションの内部は驚くほど堅牢になる。

今日から `any` を見かけたら、一度深呼吸して「これ、`unknown` にできないか?」と自問自答してみてほしい。それが、君を一段上のエンジニアへと引き上げるはずだ。

応援しているよ。また現場で会おう。

コメント

タイトルとURLをコピーしました