第32章:any卒業①(unknownへの切り替え)🎓🧷
ねらい🎯
anyの「型チェック無効化スイッチ」状態を減らして、壊れにくいコードに近づける🛡️✨- まずは第一歩として、
anyをunknownに置き換える流れを身につける👣 - 「中身が分からない値」は 境界で受け止めて、確認してから使う癖をつける🚪📦✅
今日のゴール✅
anyを見つけられる🔍any→unknownに置換できる🔁unknownを安全に使うための「最小の確認」を入れられる🧪✅- そして大事:**
unknownを広げずに“境界に寄せる”**感覚が分かる🧱🌱
まず知っておきたい:any が危ない理由💣😵💫
any は「何でもできる」代わりに、TypeScript の型チェックがほぼ効かなくなる“脱法ハッチ”です🚪💨
プロパティもメソッドも、存在してなくても通ってしまい、実行時に落ちる可能性が上がります⚠️
TypeScript の公式ドキュメントでも、any は型チェックを段階的に外すための手段で、unknown とは安全性が違うと説明されています。 (TypeScript)
unknown って何?🧩❓(ざっくり:中身不明の箱📦)


unknownは **「何が入ってるか分からない」**を表す型📦- どんな値でも入れられるけど、そのままでは触れない(= 安全)🛡️
- だから「確認してから使う」流れを自然に強制できます✅
any と unknown の違いは、unknown だと型ガード(確認)が必要になる点がポイントです🧷
公式の説明や例でも、unknown は any より安全な代替として扱われています。 (TypeScript)
いつ unknown を使うの?🧭✨(使いどころは“境界”)
unknown は、だいたいここで出てきます👇
JSON.parse()の結果(中身が何か分からない)🧾- API から返ってきた JSON(形が保証されない)🌐
- 外部ライブラリ・プラグイン・イベントの
payload(型が曖昧)🧰 - ユーザー入力(フォーム、URLクエリ、ローカルストレージ等)⌨️🫧
ここでの合言葉はこれ👇 **「境界では unknown で受けて、内側では型を確定させる」**🚪➡️🏠✅
手順👣:any → unknown に置き換える“安全ステップ”🛟
1) any を見つける🔍
よくある場所👇
: anyas anyany[]Record<string, any>JSON.parse(...)をそのまま使ってる箇所
2) まず置換:any → unknown 🔁🧷
「とりあえず unknown にする」だけで、危ない操作がコンパイルエラーで止まるようになります🚦
3) unknown を触る場所に“確認”を入れる✅
確認のやり方は色々あるけど、この章では 最小の確認だけやります🧁 (細かい絞り込みテクは次の章で強化🔍🧩)
例①:JSON.parse の any を卒業🎓🧾
ビフォー😵💫(any でスルーしちゃう)
type User = { id: string; name: string };
export function parseUser(json: string): User {
const obj: any = JSON.parse(json);
return { id: obj.id, name: obj.name.toUpperCase() };
}
これ、name が無かったり null だったりすると実行時に落ちます💥
アフター✨(unknown で受けて、確認してから使う)
type User = { id: string; name: string };
export function parseUser(json: string): User {
const raw: unknown = JSON.parse(json);
if (!isRecord(raw)) {
throw new Error("Invalid JSON: not an object");
}
const id = raw["id"];
const name = raw["name"];
if (typeof id !== "string") {
throw new Error("Invalid JSON: id must be string");
}
if (typeof name !== "string") {
throw new Error("Invalid JSON: name must be string");
}
return { id, name: name.toUpperCase() };
}
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null;
}
ポイント👇
unknownにした瞬間、雑なアクセスは止められる🚦- “使う直前”に **型チェック(確認)**してから進む✅🧷
例②:fetch().json() の戻りを unknown で受ける🌐🧪
Response.json() は型的に扱いがゆるくなりがちなので、境界として unknown で受けるのが安全です🛡️
ビフォー😬
const data: any = await (await fetch("/api/user")).json();
console.log(data.user.name);
アフター✨
type ApiUser = { user: { name: string } };
const raw: unknown = await (await fetch("/api/user")).json();
if (!isApiUser(raw)) {
throw new Error("API response is invalid");
}
console.log(raw.user.name);
function isApiUser(value: unknown): value is ApiUser {
if (!isRecord(value)) return false;
const user = value["user"];
if (!isRecord(user)) return false;
return typeof user["name"] === "string";
}
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null;
}
こうしておくと、API が壊れても「静かにバグる」より先に「ちゃんと止まる」方向に寄ります🛑✨
“unknown化”のコツ🌸(失敗しにくい考え方)
コツ1:unknown をアプリの奥まで運ばない🚫📦
unknown のままアプリ内部に持ち込むと、毎回チェックが必要でしんどいです😵💫
境界で受けて、早めに型を確定させましょう✅
コツ2:「確認→型確定→それ以降は普通に書く」🧷➡️🧠
- 境界:
unknown - 内側:ちゃんと型が付いた値(
Userとか)
これが一番ラクで強いです💪✨
Lintで any を増やさない🚫🧯(おすすめ設定)
@typescript-eslint/no-explicit-any を有効にすると、明示的な any を検出できます👮♀️⚠️
ルールページでも、unknown が代替案として挙げられています。 (TypeScript ESLint)
例:Flat Config の最小イメージ🧩
// eslint.config.mjs の一例(ルールだけ抜粋)
export default [
{
rules: {
"@typescript-eslint/no-explicit-any": "error",
},
},
];
(Flat Config 例も公式ルールページに載っています📄) (TypeScript ESLint)
どうしても any を使いたい時の“最小ダメージ”戦略🛟⚠️
「今すぐ全部直せない…😭」は普通にあります。そんな時は👇
✅ 方針
- アダプタ(境界)に閉じ込める🧱
- 理由を書く📝
- 後で直せるように 小さく隔離📦
例:1行だけ抑える(理由コメントつき)🧯
// TODO: 外部ライブラリの型が不完全。次のタイミングで型定義を改善する。
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
const x: any = legacyLib.getValue();
ESLint の無効化コメントの書き方は定番として知られています。 (Stack Overflow)
AI活用ポイント🤖✨(お願い方+チェック観点✅)
① any 探し&置換案を出してもらう🔍
お願い例👇
- 「このプロジェクトで
any/as anyの使用箇所を列挙して、unknownへの置換案を提案して」 - 「境界(API/JSON.parse/外部入力)だけ
unknownにして、アプリ内部では型を確定させる方針で直して」
② “確認が足りない場所”をレビューしてもらう✅
お願い例👇
- 「
unknownを触っている箇所で、型チェック不足の可能性がある場所を指摘して」 - 「この型ガード、抜け道ある?(null/配列/ネスト/型違い)」
③ でも最後は自分で確認👀🧪
AIの提案は便利だけど、実行時チェックの正しさは人間の目で最終確認が安心です🧷✨
ミニ課題✍️🎀(手を動かして覚える!)
次のコードの any を unknown に変えて、落ちないようにしてね✅
お題コード🧩
type Settings = { theme: "light" | "dark"; fontSize: number };
export function readSettings(json: string): Settings {
const obj: any = JSON.parse(json);
return {
theme: obj.theme,
fontSize: obj.fontSize,
};
}
やること✅
obj: anyをraw: unknownに変更🔁themeが"light" | "dark"かチェック🚦fontSizeが number かチェック🔢- ダメなら
throw new Error(...)で止める🛑
章末チェックリスト🧿✨
anyを見つけたら、まずunknownに置けた?🔁unknownを触る前に、最小の確認を入れた?✅unknownをアプリの奥まで運んでない?🚫📦- “境界で受けて、内側で型確定”になってる?🚪➡️🏠
@typescript-eslint/no-explicit-anyで増殖を防げてる?👮♀️⚠️ (TypeScript ESLint)
(ミニ豆知識)2026年1月25日時点の TypeScript 周辺の動き🧠✨
- 安定版としては TypeScript 5.9 系が公開されているのが確認できます(GitHub Releases 上で 5.9 が先頭に表示)。 (GitHub)
- TypeScript 6.0 は「橋渡し(bridge)」的な位置づけで、TypeScript 7(ネイティブ化)に向けた計画が公式ブログで説明されています。 (Microsoft for Developers)