TypeScript 6.0 がやってきた
TypeScript 6.0 が正式リリースされました。個人的にこのリリースをひと言で表すなら、「実用性の強化と歴史的転換点の両立」です。型推論の微妙だけど重要な改善、モジュール解決の現代化、そしてTemporal APIやES2025対応など、日々の開発体験に直結する変更がずらりと並んでいます。
また、このリリースにはもう一つ大きな意味があります。TypeScript 7.0 ではGoで実装されたネイティブポートが基盤となることが予告されており、TS 6.0 は TS 5.x と次世代をつなぐ橋渡し的なバージョンに位置付けられます。本記事では、全機能を網羅的に解説します。
本記事では、公式ブログ(Announcing TypeScript 6.0)をベースに、各機能の技術的な背景と実務への影響を詳しく解説していきます。
型推論の改善!this を使わない関数の新しい挙動
これまでの問題
TypeScript のメソッド構文(オブジェクトリテラル内の関数定義)には、長年にわたって一つの「ちぐはぐさ」がありました。メソッド構文で書いた関数が this を一切参照しない場合でも、TypeScript はその関数を「this に依存する可能性のある関数」として低い優先度で型推論していたのです。
具体的には、コールバックとして渡したときに期待通りの型推論が得られないケースがありました。同じ処理内容であっても、アロー関数で書いた場合と通常のメソッド構文で書いた場合とで、型推論の結果が異なってしまうという現象が起きていました。
TypeScript 6.0 での変更内容
TypeScript 6.0 では、メソッド構文で定義された関数が this を一切使用しない場合、アロー関数と同等の「高優先度な型推論コンテキスト」として扱われるようになりました。この改善はコミュニティコントリビューターの Mateusz Burzyński 氏によって実装されたものです。
変更前・変更後の挙動をコードで確認してみましょう。
// 変更前(TS 5.x)
const obj = {
// メソッド構文:this を使わなくても低優先度として扱われていた
transform(x: string) {
return x.toUpperCase();
}
};
// 変更後(TS 6.0)
const obj = {
// this を参照しない → アロー関数と同等の高優先度で推論
transform(x: string) {
return x.toUpperCase(); // 型推論がアロー関数と同じ動作に
}
};実務への影響
この変更は、既存コードの型エラーを引き起こす可能性があります。特に、意図的に低コンテキスト感度を利用していたパターンが存在する場合は注意が必要です。ただし、大多数のケースでは「期待通りに動かなかったものが正しく動くようになる」という恩恵を受けられるはずです。
チームでTypeScriptを運用している場合は、tsc --noEmit で型エラーの有無を確認してからアップグレードを進めることをお勧めします。
関数の書き方 | this の使用 | TS 5.x での推論優先度 | TS 6.0 での推論優先度 |
|---|---|---|---|
アロー関数 | 不可 | 高 | 高(変化なし) |
メソッド構文 | なし | 低 | 高(改善) |
メソッド構文 | あり | 低 | 低(変化なし) |
モジュール解決の強化:#/ サブパスインポートと新しい組み合わせ対応

#/ で始まるサブパスインポートのサポート
Node.js の最近のバージョンでは、package.json の imports フィールドに #/ プレフィックスを使ったサブパスインポートが使えるようになりました。TypeScript 6.0 はこれに対応し、--moduleResolution nodenext または --moduleResolution bundler の設定下でサポートされます。
従来のサブパスインポートでは以下のような記述が必要でした。
// package.json (従来)
{
"imports": {
"#utils": "./dist/utils.js",
"#utils/string": "./dist/utils/string.js",
"#utils/array": "./dist/utils/array.js"
}
}これが #/ プレフィックスを使ったワイルドカード形式で簡潔に書けるようになります。
// package.json(TypeScript 6.0 対応後)
{
"imports": {
"#/*": "./dist/*"
}
}
// 利用側
import { formatDate } from '#/utils/date';
import { parseQuery } from '#/utils/query';ディレクトリ構造が深くなりがちなモノレポや大規模プロジェクトでは、この記述の簡潔さは非常に助かります。パスエイリアスの管理コストが大幅に下がるため、積極的に活用したい機能です。
--moduleResolution bundler と --module commonjs の組み合わせ対応
これまで、--moduleResolution bundler は --module esnext または --module preserve との組み合わせしか許可されていませんでした。これは CommonJS 環境でバンドラーを使う場合に不便で、workaround として esnext を指定しつつ実際には CommonJS 出力を使う、という複雑な設定をしているプロジェクトも少なくありませんでした。
TypeScript 6.0 からは --moduleResolution bundler と --module commonjs の組み合わせが正式にサポートされます。
// tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"moduleResolution": "bundler", // ← TS 6.0 から valid
"target": "es2020"
}
}Webpack や esbuild を使いつつ出力は CommonJS、というごく一般的な構成でもスッキリとした tsconfig が書けるようになりました。
モジュール解決設定の選択指針
モジュール解決 | 対応する | 主なユースケース |
|---|---|---|
node16 / nodenext | node16 / nodenext | Node.js ネイティブ ESM/CJS |
bundler | esnext / preserve / commonjs(6.0 新) | Vite, webpack, esbuild 等バンドラー利用 |
classic / node10 | commonjs 等 | レガシーコード(非推奨) |
TypeScript 7.0 への橋渡し:--stableTypeOrdering フラグ
なぜこのフラグが必要なのか
TypeScript 7.0 では、型の内部処理において「型の並び順の安定性」が保証される変更が予定されています。現行の TypeScript では、特定の条件下で型の比較・表示順序が非決定的(実行するたびに変わる可能性がある)になるケースが存在します。これは型エラーメッセージの見た目やエディタ補完の順序に影響することがありました。
TypeScript 7.0 ではこの挙動を修正する予定ですが、一方でこの修正によって一部の型チェック結果が変わる可能性もあります。そこで TypeScript 6.0 では、7.0 での挙動を先取りして確認するための移行支援フラグとして --stableTypeOrdering が追加されました。
フラグの使い方と注意点
// tsconfig.json
{
"compilerOptions": {
"stableTypeOrdering": true
}
}ただし、このフラグを有効にすると最大 25% の速度低下が発生します。これは本番環境での常時利用には適していません。あくまでも TypeScript 7.0 への移行準備として、CI で定期的に実行して型エラーが出ないかを確認する用途に留めておくべきでしょう。
本番ビルドやローカル開発では引き続き通常の設定を使い、週次の CI ジョブなどで --stableTypeOrdering を有効にした型チェックを走らせておく、というアプローチが現実的かと思います。
項目 | 内容 |
|---|---|
目的 | TypeScript 7.0 移行前の互換性確認 |
速度影響 | 最大 25% 低下 |
本番利用 | 非推奨 |
推奨用途 | CI での定期チェック、移行前の事前確認 |
ES2025 対応と新しい標準ライブラリの追加

es2025 ターゲット・ライブラリオプションの追加
TypeScript 6.0 では es2025 が --target および --lib の選択肢として追加されました。これにより、RegExp.escape、Promise.try、そして Iterator/Set の各メソッドが es2025 lib に移動しています。
esnext を使っていたプロジェクトでは、これらのメソッドが既に使えていたはずですが、es2025 として明示的に指定できるようになったことで、「どのECMAScriptバージョンの機能を使っているか」がより明確になります。
RegExp.escape のサポート
RegExp.escape は、文字列内の正規表現の特殊文字をエスケープしてくれる静的メソッドです。これまで自前で実装するか、サードパーティライブラリに頼るしかなかった処理が、言語標準として使えるようになります。
// RegExp.escape の使用例
const userInput = 'Hello (World)?';
const escaped = RegExp.escape(userInput);
// => 'Hello \\(World\\)\\?'
const regex = new RegExp(escaped);
console.log(regex.test('Hello (World)?')); // trueユーザー入力を正規表現に組み込む処理は XSS に近い脆弱性(ReDoS: Regular Expression Denial of Service)につながることもあります。標準の RegExp.escape を使うことで、安全で可読性の高いコードが書けるようになります。
Promise.try のサポート
Promise.try は、同期・非同期の処理を統一的にPromiseとして扱うためのメソッドです。従来は Promise.resolve().then(() => syncOrAsync()) のような書き方をすることが多かったですが、Promise.try を使うとより意図が明確になります。
// 従来のアプローチ
Promise.resolve()
.then(() => mightThrowSync())
.catch(handleError);
// Promise.try を使った書き方
Promise.try(() => mightThrowSync())
.catch(handleError);Iterator・Set の新メソッド
ES2025 では Iterator と Set に新しいメソッドが追加されています。TypeScript 6.0 の es2025 lib でこれらの型定義が提供されます。
メソッド | 種別 | 概要 |
|---|---|---|
| Iterator | 配列の map に相当するイテレータ変換 |
| Iterator | 条件でフィルタリング |
| Iterator | 先頭 n 件を取得 |
| Iterator | 先頭 n 件をスキップ |
| Set | 2つのセットの和集合 |
| Set | 2つのセットの積集合 |
| Set | 2つのセットの差集合 |
| Set | 部分集合かどうかを判定 |
特に Iterator のメソッドチェーンは、大量データを扱う際に中間配列を生成せずに処理できるため、メモリ効率の面で恩恵を受けられます。
Temporal API:長年の課題だった日時操作がついに型安全に
Temporal API とは
JavaScript の日時操作は長年にわたって Date オブジェクトの設計上の問題に悩まされてきました。ミュータブルであること、タイムゾーン処理が不十分であること、月が0始まりであることなど、数多くの設計ミスが知られています。そのため多くのプロジェクトでは dayjs や date-fns、Luxon などのサードパーティライブラリが事実上の標準となっていました。
Temporal API はこれらすべての問題を解決する新しい日時処理APIです。ECMAScript プロポーザルとして長い間開発が続けられてきましたが、ついにステージ4(仕様確定)に到達しました。TypeScript 6.0 では ESNext の lib ターゲット向けにTemporal APIの型定義が提供されます。
Temporal API の主要クラスと使い方
Temporal API では目的別に専用のクラスが用意されています。
クラス | 表現するもの | 典型的な用途 |
|---|---|---|
| 絶対時刻(UTC基準) | ログのタイムスタンプ、API レスポンス |
| タイムゾーン付き日時 | カレンダー、スケジュール管理 |
| 時刻なし日付 | 誕生日、祝日 |
| 時刻のみ | 営業時間、アラーム |
| タイムゾーンなし日時 | ローカルでの日時表示 |
| 時間の長さ | 経過時間、期限計算 |
// Temporal API の使用例
// 現在時刻(UTC)
const now = Temporal.Now.instant();
console.log(now.toString()); // 2025-03-26T02:00:00Z
// タイムゾーン付き日時
const tokyoNow = Temporal.Now.zonedDateTimeISO('Asia/Tokyo');
console.log(tokyoNow.toString());
// 日付の計算(型安全)
const today = Temporal.Now.plainDateISO();
const nextWeek = today.add({ days: 7 });
console.log(nextWeek.toString()); // 1週間後の日付
// Duration の比較
const duration1 = Temporal.Duration.from({ hours: 1, minutes: 30 });
const duration2 = Temporal.Duration.from({ hours: 2 });
console.log(Temporal.Duration.compare(duration1, duration2)); // -1(duration1 が小さい)Temporal API の最大の魅力は「イミュータブル」であることです。Date オブジェクトは setMonth() などのメソッドがオブジェクト自身を書き換えるため、意図しない副作用が起きやすい構造でした。Temporal API のすべてのオブジェクトは不変であり、変換メソッドは必ず新しいオブジェクトを返します。
// Date の問題(ミュータブル)
const date = new Date('2025-01-01');
const nextMonth = date; // 参照コピー!
nextMonth.setMonth(date.getMonth() + 1);
console.log(date.toISOString()); // 2025-02-01 ← 元のdateも変わってしまう!
// Temporal の正しい設計(イミュータブル)
const date2 = Temporal.PlainDate.from('2025-01-01');
const nextMonth2 = date2.add({ months: 1 }); // 新しいオブジェクトを返す
console.log(date2.toString()); // 2025-01-01(不変)
console.log(nextMonth2.toString()); // 2025-02-01個人的には、TypeScript プロジェクトで Temporal API が使えるようになったことは非常に大きな変化だと感じています。特に金融系や予約管理など、日時の精度が求められるシステムでは、サードパーティライブラリへの依存を減らせる可能性があります。ただし、ランタイムでの対応状況(ブラウザ・Node.js バージョン)は別途確認が必要です。
Map の getOrInsert / getOrInsertComputed と lib.dom の整理
Map の upsert 系メソッド
ECMAScript の「upsert」プロポーザルがステージ4に到達し、Map に getOrInsert と getOrInsertComputed の2つのメソッドが追加されました。TypeScript 6.0 の esnext lib でこれらの型定義が利用できます。
これまで「Mapにキーが存在しなければ初期値を設定して取得する」という処理は、冗長な書き方を強いられていました。
// 従来のアプローチ(冗長)
const cache = new Map<string, number[]>();
function addToGroup(key: string, value: number) {
if (!cache.has(key)) {
cache.set(key, []);
}
cache.get(key)!.push(value); // Non-null assertion が必要
}
// getOrInsert を使った書き方
function addToGroupNew(key: string, value: number) {
const group = cache.getOrInsert(key, []);
group.push(value); // 型安全!
}
// getOrInsertComputed:初期値を遅延計算
function addToGroupLazy(key: string, value: number) {
const group = cache.getOrInsertComputed(key, () => []);
group.push(value);
}getOrInsert と getOrInsertComputed の使い分けについては、初期値の生成コストが低い場合は getOrInsert、配列やオブジェクトのように毎回新しいインスタンスを生成したい場合や、生成コストが高い場合は getOrInsertComputed を使うのが適切です。
メソッド | 初期値の渡し方 | 適したケース |
|---|---|---|
getOrInsert(key, value) | 値を直接渡す | プリミティブ値、既存のインスタンス |
getOrInsertComputed(key, fn) | 生成関数を渡す | 配列・オブジェクト(毎回新規生成) |
lib.dom が dom.iterable を内包
これまで lib.dom と lib.dom.iterable は別々のライブラリ定義として存在しており、NodeList や HTMLCollection を for...of でループしたい場合は両方を lib に指定する必要がありました。
// TS 5.x までの tsconfig
{
"compilerOptions": {
"lib": ["dom", "dom.iterable", "esnext"] // 両方必要だった
}
}// TS 6.0 からは dom だけで OK
{
"compilerOptions": {
"lib": ["dom", "esnext"] // dom.iterable は dom に統合済み
}
}地味な変更に見えますが、新しくプロジェクトを立ち上げる際の tsconfig の設定ミスを防げる改善です。「NodeList が iterable じゃないと言われて dom.iterable を追加する」というハマりポイントが解消されます。
JavaScriptで書かれた最後のTypeScript — 7.0 は Go へ
歴史的な転換点
TypeScript 6.0 は、JavaScript で実装された TypeScript の最後のメジャーリリースです。TypeScript はその誕生から現在まで、TypeScript 自身(つまり JavaScript)でコンパイラが実装されてきました。これは「犬の餌を犬が食べる(dogfood)」アプローチとして TypeScript の実用性を証明するものでもありました。TypeScript 7.0 での Go 移行は、パフォーマンス上の理由から行われるものであり、言語仕様自体(型システムや構文)の大きな変化を伴うわけではありません。
なぜ Go なのか
大規模プロジェクトでは TypeScript の型チェックが数十秒〜数分かかることが珍しくありません。Go によるネイティブ実装は、現行の JavaScript 実装と比較してはるかに高速な実行が期待されています。Microsoft が公開したベンチマークでは、10倍以上の高速化が示されています。
実装言語 | 型チェック速度 | メモリ効率 | |
|---|---|---|---|
TypeScript 6.0 以前 | JavaScript (TypeScript) | ベースライン | ベースライン |
TypeScript 7.0(予定) | Go | 最大10倍以上の高速化 | 大幅改善 |
TS 6.0 はブリッジバージョン
TypeScript 6.0 は TS 5.x と TS 7.0 の橋渡し役として設計されています。前述の --stableTypeOrdering フラグはその典型例で、「今のうちに TS 7.0 への準備を始めてください」というメッセージが込められています。
Go 移行という大きな変化の中でも、TypeScript チームは開発者の移行をスムーズにするための細やかな配慮を続けています。TypeScript の API 互換性や型構文は引き続き維持される予定なので、アプリケーションコード自体に大きな変更は不要なはずです。
とはいえ、TypeScript コンパイラの挙動に依存したビルドツールやプラグイン(ts-node、ts-jest、各種 webpack loader など)は対応が必要になる可能性があります。エコシステムの動向を注視していく必要があるでしょう。
アップグレードガイドと注意点
アップグレード手順
TypeScript 6.0 へのアップグレードは以下の手順で進めることを推奨します。
# npm の場合
npm install --save-dev typescript@6
# yarn の場合
yarn add --dev typescript@6
# pnpm の場合
pnpm add --save-dev typescript@6インストール後、まず型チェックのみを実行して既存コードへの影響を確認します。
# 型エラーの確認(コンパイルはしない)
npx tsc --noEmit
# strict モードで確認したい場合
npx tsc --noEmit --strict破壊的変更のチェックリスト
TypeScript 6.0 でとくに注意すべき変更点を以下にまとめます。
変更内容 | 影響範囲 | 対応方法 |
|---|---|---|
this を使わないメソッド構文の型推論変更 | コールバックとして渡されるメソッド | 型エラーが出た箇所を個別確認 |
--moduleResolution bundler + commonjs の許可 | tsconfig の設定エラーではなく追加機能なので影響なし | — |
lib.dom が dom.iterable を内包 | lib 設定 | dom.iterable を削除しても可(そのままでも可) |
各種 lib の型定義追加(Temporal 等) | ESNext/ES2025 使用コード | 型の衝突がないか確認 |
段階的な移行アプローチ
大規模なプロジェクトでは、すべてを一度に移行しようとするとリスクが高まります。以下のような段階的アプローチが有効です。
まずは開発環境のみで TypeScript 6.0 を試し、型エラーが発生する箇所を洗い出してください。次に、エラーが発生した箇所が意図した変更による改善なのか、それとも既存コードの問題が顕在化したものなのかを判断します。最後に、修正が完了したらステージング環境でのテストを経て本番に適用します。
特に型エラーが多数発生する場合は、@ts-expect-error や一時的な // @ts-ignore でエラーを抑制しつつ、段階的に対応していくのも現実的な選択肢です。
まとめ
TypeScript 6.0 の主要な変更点を振り返ると、以下のように整理できます。
機能・変更カテゴリ | 影響度 |
|---|---|
this なしメソッドの型推論改善 | 型システム 中(既存コードへの影響あり) |
#/ サブパスインポートのサポート | モジュール解決 低(新機能追加) |
bundler + commonjs の組み合わせ許可 | モジュール解決 低(新機能追加) |
--stableTypeOrdering フラグ | 移行支援 低(オプトイン) |
es2025 lib の追加 | 標準ライブラリ 中(新機能利用可) |
Temporal API の型定義 | 標準ライブラリ 高(日時処理の根本的改善) |
Map の getOrInsert 系メソッド | 標準ライブラリ 低(新機能追加) |
RegExp.escape | 標準ライブラリ 低(新機能追加) |
lib.dom が dom.iterable を内包 | 標準ライブラリ整理 低(後方互換あり) |
JS実装の最終バージョン | 歴史的転換点 長期的に高 |
個人的には、今回のリリースで最も注目しているのは Temporal API の型定義サポートです。日時操作はすべてのWebアプリに存在する基本的な処理であり、Date の設計上の問題に悩まされてきた開発者は多いはずです。ランタイムサポートの普及には時間がかかりますが、TypeScript の型定義が整ったことで、新規プロジェクトでは積極的に採用を検討できるタイミングになりました。
そして「JavaScriptで書かれた最後のTypeScript」という側面。TypeScript 7.0 での Go 移行が開発体験にどのような変化をもたらすのか、今から楽しみにしています。大規模プロジェクトでの型チェックが劇的に高速化されることで、型を積極的に活用する設計が一層しやすくなるはずです。
アップグレードを検討されている方は、まず tsc --noEmit で型エラーの有無を確認し、影響範囲を把握してから移行を進めていただければと思います。















