【実務・中級編】 unknown型の役割と型ガード – TypeScript実践ガイド

`any`は「思考停止の麻薬」、`unknown`は「信頼の証明」である

フロントエンドの現場でコードレビューをしていると、どうしても遭遇してしまうのが「とりあえず動けばいい」という理由で蔓延する `any` 型だ。君も経験があるだろう? APIからのレスポンスを `any` で受けて、その場を凌いだ結果、2ヶ月後に「`undefined` を読み取れません」というエラーで深夜に呼び出されるあの絶望感。

今回は、そんな `any` の暴走を止め、TypeScript本来の堅牢さを取り戻すための「`unknown` 型」と「型ガード」の作法について、泥臭い実務の知見を交えて語ろうと思う。

—

`unknown` 型とは、TypeScriptからの「警告」である

一言で言えば、`unknown` は「何が入っているか分からない。だからこそ、使う前に必ず安全を確認しろ」というTypeScriptからの強いメッセージだ。

`any` が「何でも許す(型安全を放棄する)」のに対し、`unknown` は「入ることは許すが、使うことは一切許さない(型安全を強制する)」という対照的な性質を持つ。

ブラウザの実行環境であるJavaScriptにはそもそも「型」という概念が存在しない。TypeScriptの型チェックは、あくまで我々開発者が書いたコードをコンパイルする段階で行われる「静的解析」だ。`unknown` を使うということは、「このデータが外部(APIやLocalStorageなど)から来るブラックボックスであることを、コード上で明示的に認める」という、極めてプロフェッショナルな誠実さを意味するんだ。

—

なぜ `any` ではいけないのか?

`any` を使った瞬間、TypeScriptのコンパイラは「もう君のことは知らない、好きにしてくれ」と匙を投げる。その結果、本来ならコンパイル時に検知できたはずのプロパティのタイポや、存在しないメソッドの呼び出しが、全てブラウザ実行時のランタイムエラーとして直撃する。

対して `unknown` は、「型ガード(Type Guard)」を強制する。
「この値が本当に `string` なのか?」「本当にこのオブジェクトには `id` があるのか?」という確認作業を、コードに書かざるを得ない状況を作るんだ。

—

実務で使える「型ガード」のベストプラクティス

現場で最も安全かつスマートなのは、`typeof` や `instanceof` を使った型ガード、そしてユーザー定義型ガードだ。以下のコードを見てほしい。

/

  • APIから返ってくる未知のレスポンスを想定

/
const response: unknown = await fetch(‘/api/user’).then((res) => res.json());

/

  • 1. 基本的な型ガード (typeof)
  • 文字列であることが確定したブロック内では、自動的にstringとして扱われる

/
if (typeof response === ‘string’) {
console.log(response.toUpperCase()); // ここでは安全に文字列操作ができる
}

/

  • 2. ユーザー定義型ガード
  • 実務で最も出番が多い「オブジェクトの構造チェック」

/
interface User {
id: number;
name: string;
}

function isUser(data: unknown): data is User {
// dataがnullではなく、かつobject型であり、idとnameを持っているかを確認
return (
typeof data === ‘object’ &&
data !== null &&
‘id’ in data &&
‘name’ in data
);
}

if (isUser(response)) {
// このブロック内ではresponseはUser型として扱われる
console.log(`User ID: ${response.id}, Name: ${response.name}`);
} else {
console.error(‘期待したデータ構造ではありません’);
}

このコードのポイント

  • `is` キーワード: `data is User` と書くことで、TypeScriptに「この関数が `true` を返したなら、それは `User` 型である」と教えているんだ。
  • nullチェック: JavaScriptの `typeof null` は `’object’` になるという歴史的経緯(バグ)を、`data !== null` でしっかりカバーしている。ここが分かっているだけで、バグの発生率はぐっと下がる。

—

さらなる高みへ:`unknown` を使いこなすために

実務では、ここからさらに `zod` などのバリデーションライブラリを組み合わせて使うのが現代のフロントエンドの最適解だ。

もし君が大規模なアプリを開発しているなら、`unknown` で受け取ったデータを、実行時にスキーマ定義に基づいて検証し、パスしたものだけを型付けされたデータとして扱う。そうすれば、`if` 文を何重にも書く必要はなくなり、コードは劇的にスッキリする。

最後に、君に伝えたいこと

`unknown` を使うのは、最初は少し面倒に感じるかもしれない。しかし、その「面倒」こそが、将来の自分を助ける「保険」になる。

「型を書くこと」は「制約を増やすこと」ではなく、「仕様を確定させること」だ。曖昧なまま突き進むのではなく、`unknown` を入り口に置いて、一つずつコードの安全を証明していく。そんな泥臭い積み重ねができるエンジニアこそが、信頼されるアーキテクトになれると僕は信じている。

明日からのコードで、`any` を見かけたら、そっと `unknown` に書き換えて、型ガードを書いてみてくれ。きっと、エディタの波線が消える瞬間の心地よさが理解できるはずだ。

コメント

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