エンジニアの皆さん、お疲れ様。今日もコードと格闘しているかな。
さて、TypeScriptを触り始めてしばらく経つと、必ずと言っていいほどぶち当たる壁がある。「なぜ型をちゃんと書かなきゃいけないのか」という問いだ。プロジェクトが大きくなればなるほど、この規律を守れるかどうかが、プロダクトの寿命を左右する。
今日は、その最前線で「型を守るための防波堤」となる `compilerOptions.noImplicitAny` について話をしよう。
—
なぜ `noImplicitAny` は「絶対」なのか
`noImplicitAny`。これは、TypeScriptの設定ファイル `tsconfig.json` において、最も妥協してはいけない設定項目だ。
デフォルトでは、TypeScriptは型が明示されていない変数や引数を「まあ、とりあえず `any` 型として扱っておくか(暗黙の `any`)」という緩い対応をとる。これが諸悪の根源だ。JavaScriptの「何でもあり」という悪しき柔軟性がそのまま残ってしまう。
ブラウザの実行環境であるJavaScriptエンジン(V8など)は、型なんてものは知らない。実行時に動的に値を解釈するだけだ。しかし、TypeScriptの目的は「実行前にエラーを潰す」ことにある。`any` を許容するということは、TypeScriptという強力な静的解析ツールを「ただのコメント」に成り下がらせる行為に他ならない。
現場のコードベースで `noImplicitAny: false` にしているプロジェクトに出会うと、僕は冷や汗が出る。そこには「いつか必ず発生する、原因不明のランタイムエラー」という時限爆弾が埋め込まれているからだ。
—
実践:型定義をサボると何が起きるのか
例えば、こんなコードを書いていないだろうか。
// noImplicitAny: false の世界で生きる、危険なコード
function calculateTotal(price, tax) {
// ここで price や tax が何者か分からないため、
// 意図しない文字列連結や計算エラーが起きてもコンパイルは通ってしまう
return price + (price tax);
}
console.log(calculateTotal(100, 0.1)); // 110
console.log(calculateTotal(“100”, 0.1)); // “100” + 10 = “10010” という惨劇
このコード、TypeScriptを使っている意味が全くないよね。実行して初めて「あ、文字列だったか」と気づく。これではJavaScriptで書いているのと変わらない。
`noImplicitAny: true` を有効にすると
この設定を `true` にすると、TypeScriptコンパイラはコンパイル時に容赦なく警告を吐き出してくれる。
// tsconfig.json
{
“compilerOptions”: {
“noImplicitAny”: true
}
}
// 修正後のコード(これが本来あるべき姿)
function calculateTotal(price: number, tax: number): number {
// 引数の型を明示することで、コンパイル時点で型安全が保証される
return price + (price tax);
}
// これなら安心。price に文字列を渡そうものなら、IDEが即座に赤波線を引いて教えてくれる。
—
現場で役立つ「型推論」との付き合い方
「毎回全部の型を書くのは面倒だ」という声も聞こえてきそうだ。だが、安心してほしい。TypeScriptには優秀な型推論がある。
`noImplicitAny` を有効にしても、代入された初期値から型が自明な場合は、明示的に型を書かなくてもコンパイラが賢く推論してくれる。
// 型を書かなくても、初期値が数値なので TypeScript はこれは number だと理解する
let count = 10;
// 代入時に型が確定するため、後から文字列を入れることはできない
// count = “20”; // エラー: Type ‘string’ is not assignable to type ‘number’.
現場のベストプラクティスとしては、「初期値がない場合、あるいは関数の引数・戻り値は必ず型を明示する」というルールを徹底することだ。これだけで、コードの品質は劇的に向上する。
—
今すぐやるべきアクション
もし君が参画しているプロジェクトで `noImplicitAny` が `false` になっているなら、今すぐ `true` に変えてほしい。
「いや、既存のコードが大量にエラーになるから無理だよ」という嘆きが聞こえてきそうだが、それは「今まで見て見ぬふりをしてきた爆弾を、今ようやく発見した」という喜ぶべき事態なんだ。
1. tsconfig.json を更新する
2. 発生したエラーを一つずつ潰す
3. どうしても型が特定できない場所だけ `any` を使う(ただし、これは逃げ道であることを忘れないこと)
`any` を撲滅することは、チームの開発生産性を高めるための最も確実な投資だ。型定義を書く時間を「コスト」だと思わず、「未来の自分への保険」だと考えてほしい。
TypeScriptは、君たちが書いたコードの意図を正確に理解しようと待ち構えている。その対話を拒絶するか、あるいは最大限に活かすか。それは、`tsconfig.json` のたった一行の設定に懸かっているんだ。
自信を持って設定を変えていこう。現場からは以上だ。

コメント