TypeScriptの `target` 設定:その「妥協点」があなたのアプリの命運を握っている
現場でコードを書いていると、つい「とりあえず `ESNext` にしておけば最新機能が使えて最高じゃん」と思いがちだよね。でも、ちょっと待ってほしい。その甘い判断が、数ヶ月後に「特定の古い環境でだけ謎のクラッシュをする」という、悪夢のようなデバッグ地獄を招くことになる。
今回は、TypeScriptの心臓部の一つである `tsconfig.json` の `target` プロパティについて、ただの文法解説ではなく、「ブラウザの裏側で何が起きているのか」という視点から、現場のリアルな勘所を叩き込んでいくよ。
—
1. `target` とは一体何者なのか?
`target` は、TypeScriptがコンパイルされた結果、「どの時代のJavaScript構文(ECMAScriptバージョン)として出力するか」を定義する設定だ。
例えば、`async/await`。これは比較的新しい構文だけど、これを `target: “ES5″` でビルドすると、TypeScriptは「あぁ、この環境には `async` なんて気の利いたものはないんだな」と判断し、巨大なジェネレータ関数やステートマシンに変換してくれる。
これが何を意味するか? コードが肥大化するということだ。
現場の判断基準:どこまで「過去」を背負うか
- ES5: IE11対応が必要な「死の淵」にいる現場用。ほぼ全てのコードが変換され、ビルドサイズは膨れ上がる。
- ES2015 (ES6): モダンブラウザの最低ライン。`const/let` やアロー関数はそのまま出力される。現代のフロントエンド開発の標準的な出発点だ。
- ESNext: 最新の機能を使う。ただし、出力先ブラウザが対応していない場合、実行時に即死する。
2. ポリフィル(Polyfill)との境界線を見極める
ここが一番の落とし穴だ。`target` を変えても、「新しいAPI」が使えるようになるわけではない、という点に注意してほしい。
- 構文の変換 (Transpilation): `target` が担う。(`async/await`, `class` など)
- APIの補完 (Polyfill): `core-js` などが担う。(`Promise`, `Array.prototype.includes`, `Map`, `Set` など)
つまり、`target: “ES2015″` に設定しても、ブラウザ側に `Array.prototype.includes` が実装されていなければ、`includes` を使った瞬間に `TypeError: … is not a function` でアプリは落ちる。「構文が通ること」と「APIが存在すること」は別問題だということを、心に深く刻んでおこう。
—
3. 実務で「これだけは守れ」という推奨設定
最近の現場で、僕がよく採用する `tsconfig.json` の構成案を置いておく。`target` を極端に下げず、`lib` プロパティで必要なAPIの型定義だけを拾うのが、今のフロントエンド開発の最適解だ。
{
“compilerOptions”: {
// モダンブラウザをターゲットにするのが現代の鉄則
“target”: “ES2020”,
// 実行環境で使えるAPIの型定義を指定
// 構文はES2020、DOMの操作も必要、という構成
“lib”: [“ES2020”, “DOM”, “DOM.Iterable”],
// これをtrueにすると、targetが古くても最新の構文を保とうとする(便利!)
“useDefineForClassFields”: true,
// モジュール解決のルール
“module”: “ESNext”,
“moduleResolution”: “node”
}
}
—
4. 賢いエンジニアの「検証」テクニック
最後に、自分が書いているコードが「どの構文に変換されているか」を瞬時に確認する方法を紹介する。
TypeScript公式の [TypeScript Playground](https://www.typescriptlang.org/play) を使おう。
1. 左上の `TS Config` をクリック。
2. `Target` を `ES5` や `ESNext` に切り替える。
3. 自分の書いたコードが、右側のJavaScriptペインでどう変貌するかを見る。
例えば、`??`(Null合体演算子)を `target: “ES5″` でビルドすると、驚くほど長い三項演算子の羅列に変換されるはずだ。これを見ると、「あ、自分のコードの重さはここで決まるんだな」という感覚が養われるはず。
まとめ:アーキテクトからのアドバイス
`target` 設定は、単なるテキストの書き換え設定ではない。「あなたのプロダクトが、どの時代のユーザーを切り捨てるか」という宣言だ。
- 無闇に古い `target` を指定しない: バンドルサイズとパフォーマンスが悪化する。
- `lib` を適切に管理する: 実行環境に存在しないAPIを型定義から除外することで、コンパイル時にエラーを検知できる。
- BabelやSWCとの連携を考える: 最近はTypeScript単体で変換せず、`target: “ESNext”` にして、変換の最終処理をBabelに任せるのがプロの現場のトレンドだ。
技術は常に動いている。今日設定した `ES2020` も、2年後には古臭いものになっているかもしれない。だからこそ、設定の裏にある「なぜ?」を理解し続けることが、一歩先を行くエンジニアへの近道だよ。
何か詰まったら、いつでも聞いてくれ。現場からは以上だ。

コメント