【実務・中級編】 strictPropertyInitializationのクラス初期化チェック – TypeScript実践ガイド

`strictPropertyInitialization`:TypeScriptが君のクラスを「安全」にする最後の砦

やあ。現場でコードを書いていると、つい「まあ、コンストラクタで代入し忘れても動くだろう」なんて甘い期待を抱いてしまうことはないかな?

だが、TypeScriptをガチで運用するなら、`tsconfig.json`の`strictPropertyInitialization`を無視するのは、地雷原を裸足で歩くようなものだ。今回は、この設定がなぜ重要なのか、そしてどう付き合っていくべきか、現場の視点から深掘りしていこう。

—

1. なぜ「初期化漏れ」がバグの温床になるのか

まずは、この設定がオフの時の恐ろしさを思い出してほしい。TypeScriptは本来、クラスのプロパティがコンストラクタで確実に初期化されているかを監視する。これが`strictPropertyInitialization: true`(`strict: true`に含まれる)の状態だ。

もしこれを無効にすると、TypeScriptは「お前が初期化を忘れても、俺は文句を言わないよ」というスタンスになる。しかし、JavaScriptのランタイムは正直だ。初期化されていないプロパティにアクセスすれば、例外が発生するか、あるいは運悪く`undefined`が入り込んで、後続のロジックが盛大に爆発する。

ブラウザのエンジン(V8など)は、メモリレイアウトを最適化するために、クラスのプロパティの存在を期待している。コンストラクタで初期化されていないプロパティは、静的な解析をすり抜けても、実行時に「隠れたバグ」として潜伏し続けるんだ。

—

2. 現場で直面する「初期化できない」問題とスマートな回避策

もちろん、フレームワークのライフサイクルやDI(依存性の注入)の都合上、コンストラクタで初期化するのが難しいケースもあるだろう。そんな時、多くのエンジニアがやりがちなのが`strictPropertyInitialization: false`への逃避だ。

だが、それは敗北に等しい。以下の3つのテクニックを使えば、安全性を保ったままコードをクリーンに保てる。

テクニックA:Definite Assignment Assertion(非null表明)

「絶対に初期化するから黙っていてくれ」とコンパイラに伝える記法だ。

class UserProfile {
// コンストラクタで初期化できないが、必ず初期化されることが保証されている場合
// ‘!’ を付けることでTypeScriptに初期化チェックをスキップさせる
public name!: string;

constructor() {
this.init();
}

private init() {
this.name = “John Doe”; // ここで確実に初期化する
}
}

テクニックB:Constructor Parameter Properties(推奨)

TypeScriptの糖衣構文を活かして、定義と代入を同時に行う方法だ。これが一番「TypeScriptらしい」書き方と言える。

class Product {
// コンストラクタの引数にアクセス修飾子を付けるだけで、
// プロパティ宣言と代入を省略できる(DRY原則)
constructor(
public readonly id: number,
public name: string,
private price: number
) {}
}

const item = new Product(1, “Mechanical Keyboard”, 15000);
console.log(item.name); // シンプルで堅牢

テクニックC:Maybe型(Optional)への昇華

そもそも「コンストラクタで初期化できない(=未定義の可能性がある)」なら、型自体にその性質を持たせるべきだ。

class Session {
// undefinedの可能性があるなら、素直に型で表現する
// これにより、利用側で必ずガード節を書くという「安全な設計」を強制できる
public token: string | undefined;

constructor(hasToken: boolean) {
if (hasToken) {
this.token = “SECRET_TOKEN”;
}
}
}

—

3. 結論:設定をオフにするな、設計を修正しろ

いいか、`strictPropertyInitialization`を無効にするのは、セキュリティホールを放置するのと同じだ。TypeScriptの警告は、君のコードに対する「設計の見直し要請」だと捉えてほしい。

もしコンストラクタでどうしても初期化できないなら、それはそのクラスが「複数の責務」を抱えすぎているか、コンストラクタの役割分担が間違っているサインだ。

現場でのベストプラクティス:
1. 基本は `strict: true`(もちろんこのオプションも有効)を維持する。
2. どうしても無理なら `!` 演算子で明示的にスキップさせる(多用厳禁)。
3. それでも警告が出るなら、クラス設計を分割するか、`Optional`型を正しく使う。

この設定を有効にすることで、君の書くコードは「実行時エラー」を未然に防ぐ、極めて堅牢なものになるはずだ。明日からの開発で、ぜひこの意識を持ってコードを眺めてみてくれ。TypeScriptは、君が正しく扱えば必ず最高の相棒になってくれるはずだ。

コメント

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