TypeScriptの深淵へようこそ。型システムを単なる「エラーを防ぐための道具」ではなく、コードの論理構造を厳密に定義するための「言語」として捉えられるようになると、開発の景色は一変します。
今回は、TypeScriptの型システムにおける「両端」とも言える重要な概念、`unknown`(トップ型)と`never`(ボトム型)について解説します。これらをInterfaceや型定義でどう扱うべきか、その本質を紐解いていきましょう。
—
1. 型の階層構造をイメージしよう
TypeScriptの型には「集合」としての包含関係があります。
- `unknown` (トップ型): 全ての型を包含する。宇宙そのもの。
- `never` (ボトム型): どの型も包含しない。空集合。
この二つを理解するために、まずは「箱」をイメージしてください。`unknown`は「何でも入る巨大な箱」、`never`は「何も入れられない、存在してはいけない箱」です。
—
2. `unknown`型:安全な「何でもあり」
`any`型を使って「型チェックを無効化」してしまうのは、TypeScriptの利点を捨てる行為です。そこで登場するのが`unknown`です。
なぜ `unknown` を使うのか?
外部APIからのレスポンスなど、現時点で型が確定していないとき、`unknown`を使います。`any`と決定的に違うのは、「使う前に型を絞り込まないとエラーになる」という点です。
interface UserResponse {
data: unknown; // 何が入ってくるか現時点では不明
}
function processData(response: UserResponse) {
// const name = response.data.name; // ❌ エラー! unknown型にプロパティアクセスはできません
// 型ガード(Type Guard)を使って「安全な道」を作る
if (typeof response.data === ‘object’ && response.data !== null && ‘name’ in response.data) {
console.log((response.data as { name: string }).name); // ✅ 安全にアクセス可能
}
}
ポイント: `unknown`は「今の段階では詳細を知らないが、後で厳密に確認する」という誠実な姿勢を表す型です。
—
3. `never`型:論理的な「不可能性」
`never`は、「そこには決して到達しない」ことをコンパイラに伝えるための型です。
「ありえない」を型で表現する
例えば、スイッチのケース分岐で「全てのケースを網羅したはず」という論理を保証したいときに使います。
type Status = “success” | “error”;
function handleStatus(status: Status) {
switch (status) {
case “success”:
return “成功”;
case “error”:
return “失敗”;
default:
// ここは「決して到達しないはず」の場所
const _exhaustiveCheck: never = status;
return _exhaustiveCheck;
}
}
もし将来、`Status`型に `”loading”` が追加されたらどうなるでしょうか? `default`ブロックで型エラーが発生し、「新しい状態が増えたのに処理が足りていないよ!」とコンパイラが教えてくれます。これが`never`を使った網羅性チェック(Exhaustiveness Checking)です。
—
4. Interface定義でやってはいけないこと
初心者の方が陥りやすい罠として、Interfaceのプロパティに`never`を置くケースがあります。
interface ForbiddenInterface {
id: number;
deprecatedField: never; // ❌ 意味がない
}
`never`は「値が存在し得ない」ことを意味するので、このInterfaceのインスタンスは物理的に作成不可能になります。もしフィールドを「今は使いたくない」のであれば、`never`ではなく`Optional`(`?`)を使うか、そもそも定義から消すのが正解です。
—
5. まとめ:型は「論理の証明」
最後に、今回の極意をまとめておきます。
1. `unknown`は「疑い深さ」の証明: 外部からの入力はすべて`unknown`として受け取り、必ず型ガードで中身を証明してから使う。
2. `never`は「完全網羅」の証明: `switch`文や条件分岐で、論理的な漏れがないことを型システムに担保させる。
`any`で思考停止せず、`unknown`と`never`を適切に配置する。これだけであなたの書くTypeScriptコードの信頼性は劇的に向上します。
ここをクリアできれば、もうTypeScriptの型システムが「足かせ」ではなく、強力な「味方」になっているはずです。自信を持って、次の実装に進んでくださいね!