TypeScript 6.0 発表
(devblogs.microsoft.com)- JavaScriptベースの現行コードベースにおける最後のリリースであり、Goで書かれたネイティブ移植版 TypeScript 7.0 への移行を準備するブリッジリリース
thisを使わない関数のコンテキスト感度の緩和、#/で始まるsubpath imports のサポートなど、型推論とモジュール解決の改善を含むstrictのデフォルト値をtrueに変更、targetのデフォルト値をes2025、typesのデフォルト値を[]にするなど、コンパイラオプションのデフォルト値を大幅にモダン化- ES5 ターゲット、AMD/UMD/SystemJS モジュール、
--baseUrl、--moduleResolution node10など、レガシーオプションを大規模に廃止予定(deprecation) - Temporal API、Map の
getOrInsert/getOrInsertComputed、RegExp.escapeなど、最新の ECMAScript Stage 4 提案の型サポートを追加
TypeScript 6.0 の位置づけ
- 現行の JavaScript コードベースに基づく最後のリリースであり、TypeScript 7.0(Go ネイティブ移植版)への移行に向けたブリッジの役割を担う
- TypeScript 7.0 はネイティブコードと共有メモリによるマルチスレッド処理を活用し、すでに完成にかなり近い状態
- 6.0 の変更の大半は、7.0 の導入に向けて足並みをそろえ、準備を進めるためのもの
- TypeScript 7.0 は VS Code 拡張 や npm パッケージ で先行体験できる
Beta および RC 以降の変更点
- ジェネリック呼び出し(特にジェネリック JSX 式)における関数式の型チェックを調整 — 既存コードでより多くのバグを見つけられる一方、一部のジェネリック呼び出しでは明示的な型引数が必要になる可能性がある
import()呼び出しでもimport assertion 構文(assert)の廃止拡張を適用- DOM 型を更新 — 最新の Web 標準を反映し、Temporal API 関連の調整も含む
this を使わない関数のコンテキスト感度の緩和
- TypeScript は型推論時、明示的な型を持たない引数を持つ関数を**コンテキスト依存関数(contextually sensitive function)**として分類し、推論順序で後回しにしていた
- メソッド構文で書かれた関数は暗黙の
this引数を持つため、アロー関数とは異なり常にコンテキスト依存として扱われていた- このため、オブジェクトリテラル内のメソッドの順序によって型推論が失敗することがあった
- TypeScript 6.0 では、実際には
thisを使っていない関数はコンテキスト依存と見なされない- それらの関数は型推論で優先順位が高くなり、メソッド順に関係なく正しく推論される
- Mateusz Burzyński による貢献で実装
#/ で始まる Subpath Imports のサポート
- Node.js のsubpath imports 機能は、パッケージ内部モジュールへのエイリアスを
package.jsonのimportsフィールドで定義するもの - これまでは
#の後に必ず文字が必要だったため、#/で始まるパスは使えなかった- バンドラーで
@/接頭辞の慣習に慣れた開発者に混乱を招いていた
- バンドラーで
- Node.js は最近、
#/で始まる subpath imports のサポートを開始"#/*": "./dist/*"のような簡潔なマッピングが可能に
- TypeScript 6.0 は
--moduleResolution nodenextおよびbundlerオプションでこれをサポート - magic-akari による貢献で実装
--moduleResolution bundler と --module commonjs の組み合わせを許可
- 従来
--moduleResolution bundlerは--module esnextまたは--module preserveでのみ使用可能だった --moduleResolution node(node10)の廃止により、この新しい組み合わせが多くのプロジェクトにとって最適なアップグレード経路となる- 長期的には
--module preserve+--moduleResolution bundlerまたは--module nodenextへの移行を推奨
--stableTypeOrdering フラグ
- TypeScript 内部で型に割り当てられる型 IDは処理順によって決まり、これを基にユニオン型が並べ替えられる
- 宣言順によって宣言 emit の結果が変わる予測不能な現象が起こりうる
- TypeScript 7.0 は並列型チェックを導入するため、非決定的な ID 割り当ての問題を解消するべく、内容ベースの決定的なソートアルゴリズムを使用する
- 例:
100 | 500は常に同じ順序で出力される
- 例:
- 6.0 で
--stableTypeOrderingフラグを有効にすると、7.0 の型並び替え動作と一致させて両コードベース間の差異を減らせる- 型チェック性能が最大 25% 低下する可能性がある
- 推論差異による型エラーが発生した場合は、明示的な型引数や変数アノテーションの追加で解決できる
- 6.0 から 7.0 への移行診断用だけを意図したフラグであり、長期利用は非推奨
es2025 オプション(target と lib)
- ES2025 には新しい JavaScript 言語機能はないが、ビルトイン API の型(例:
RegExp.escape)が追加される esnextにあったPromise.try、Iteratorメソッド、Setメソッドなどが**es2025に移動**- Kenta Moriuchi による貢献で実装
Temporal API の型サポート
- Stage 4 に到達したTemporal 提案のビルトイン型を TypeScript 6.0 に含めた
--target esnextまたは"lib": ["esnext"](または細分化されたesnext.temporal)で利用可能Temporal.Now.instant().subtract()、.add()などの API を型安全に利用できる- すでに複数のランタイムで利用可能で、Stage 4 として公式な JavaScript 言語の一部となっている
- Renegade334 による貢献で実装
Map の "upsert" メソッドの型サポート(getOrInsert / getOrInsertComputed)
- Map でキーの存在を確認し、なければデフォルト値を設定する反復的なパターンを簡素化
- ECMAScript の**"upsert" 提案**が Stage 4 に到達し、
MapとWeakMapに 2 つの新メソッドを追加getOrInsert: キーがなければ指定したデフォルト値を挿入して返すgetOrInsertComputed: デフォルト値の生成コストが高い場合、コールバックで遅延計算する- コールバックはキーを引数に取り、キーに基づくデフォルト値の生成にも利用できる
esnextlib に追加され、TypeScript 6.0 ですぐに利用可能- Renegade334 による貢献で実装
RegExp.escape
- 正規表現内の特殊文字をエスケープする
RegExp.escape関数がStage 4 に到達 es2025lib に含まれ、TypeScript 6.0 で利用可能- Kenta Moriuchi による貢献で実装
dom lib への dom.iterable および dom.asynciterable の統合
- 従来は
NodeList、HTMLCollectionなどでイテレーションを使うには"lib": ["dom", "dom.iterable"]を明示する必要があった - TypeScript 6.0 では
lib.dom.iterable.d.tsとlib.dom.asynciterable.d.tsの内容が**lib.dom.d.tsに完全統合**されたdom.iterable、dom.asynciterableは引き続き参照可能だが空ファイルとなる
- 主要な最新ブラウザはすべてこの機能をサポートしており、よくある混乱ポイントを取り除く利便性向上
主なデフォルト値の変更
strictのデフォルト値がtrue: ほとんどの新規プロジェクトは strict モードを望むため、従来のfalseに依存していたプロジェクトは明示的に"strict": falseの設定が必要moduleのデフォルト値がesnext: ESM が支配的なモジュール形式となった現実を反映targetのデフォルト値が最新 ES バージョン(現在はes2025): エバーグリーンなランタイムが一般化し、旧バージョン向けトランスパイルが不要にnoUncheckedSideEffectImportsのデフォルト値がtrue: 副作用専用インポートのタイプミス検出を支援libReplacementのデフォルト値がfalse: 不要なモジュール解決失敗や監視対象の増加を防ぎ、デフォルト性能を改善
rootDir のデフォルト値を . に変更
- 従来は未指定時、すべての非宣言入力ファイルの共通ディレクトリを推論して決定していた
- プロジェクトにファイルが属するかを判断するには、そのプロジェクトを読み込み・解析する必要があるという問題があった
- TypeScript 6.0 ではデフォルト値が**
tsconfig.jsonが置かれたディレクトリ**に固定される tsconfig.jsonより深い場所にソースファイルがある場合、"rootDir": "./src"などを明示的に設定する必要がある- 未設定だと
./dist/src/index.jsのような意図しない出力構造になる可能性がある
- 未設定だと
types のデフォルト値を [] に変更
- 従来は
node_modules/@types内のすべてのパッケージを自動包含しており、ビルド時間に大きなオーバーヘッドを生んでいた- 一般的なリポジトリでは数百の
@typesパッケージが推移的に含まれるケースも多い
- 一般的なリポジトリでは数百の
- TypeScript 6.0 ではデフォルト値を
[](空配列)に変更し、不要な宣言ファイルの読み込みを防ぐ - 実際にビルド時間が 20〜50% 改善した事例が確認されている
- 多くのプロジェクトでは
"types": ["node"]または"types": ["node", "jest"]などの明示設定が必要"types": ["*"]で従来の挙動を復元可能
廃止予定(Deprecation)項目
target: es5 の廃止予定
- ES5 ターゲットは IE の退役とエバーグリーンブラウザの一般化により、利用例がほとんどない
- 最小ターゲットは ES2015 に変更され、ES5 出力が必要なら外部コンパイラの使用を推奨
--downlevelIteration の廃止予定
- ES5 emit でのみ効果があったため、ES5 ターゲットの廃止に伴って目的を失う
--moduleResolution node(node10)の廃止予定
- Node.js 10 のモジュール解決アルゴリズムを反映したもので、最新の Node.js の挙動と一致しない
nodenext(Node.js を直接ターゲット)またはbundler(バンドラー / Bun 利用時)への移行を推奨
AMD、UMD、SystemJS モジュール値の廃止予定
--module amd、--module umd、--module systemjs、--module noneはいずれも未サポート- ESM がブラウザと Node.js で広くサポートされているため、バンドラーまたは ESM ターゲットへの移行が必要
--baseUrl の廃止予定
- 主に
pathsの接頭辞として使われていたが、モジュール解決の検索ルートとしても機能するため、意図しないパス解決の問題を引き起こしていた baseUrlを削除し、pathsエントリに接頭辞を直接追加する形で移行する- 例:
"@app/*": ["app/*"]→"@app/*": ["./src/app/*"]
- 例:
--moduleResolution classic の廃止予定
- TypeScript 本来のモジュール解決アルゴリズムだが、現在の実用的なケースはすべて
nodenextまたはbundlerで代替可能
esModuleInterop false と allowSyntheticDefaultImports false の廃止予定
- 両オプションを
falseに設定できなくなり、安全な interop 動作が常に有効になる import * as express from "express"→import express from "express"への調整が必要
--alwaysStrict false の廃止予定
- すべてのコードがJavaScript strict modeとして扱われるため、
await、static、privateなどを通常の識別子として使っているコードは名前変更が必要
outFile の廃止予定
- 複数の入力ファイルを 1 つに結合する機能だったが、Webpack、Rollup、esbuild、Vite などの外部バンドラーに置き換えられた
- TypeScript の中核的役割である型チェックと宣言 emit に集中するための決定
レガシー module 構文(名前空間宣言)の廃止予定
module Foo { ... }構文は強制的に廃止予定となり、namespace Foo { ... }を使う必要があるdeclare module "some-module" { ... }形式の ambient module 宣言は引き続きサポート- ECMAScript の
moduleブロック提案との衝突を避ける目的
Import asserts キーワードの廃止予定
import ... asserts { type: "json" }→import ... with { type: "json" }へ変更が必要- import assertions 提案が**import attributes 提案(
withキーワード)**へ変更されたことに伴う対応
no-default-lib ディレクティブの廃止予定
/// <reference no-default-lib="true"/>は今後サポートされず、--noLibまたは--libReplacementの使用を推奨
tsconfig.json が存在する場合のコマンドラインファイル指定エラー
tsc foo.ts実行時、同じディレクトリにtsconfig.jsonがあるとエラーになる--ignoreConfigフラグで明示的に無視可能
TypeScript 7.0 の準備
- 6.0 で廃止予定となったオプションは
"ignoreDeprecations": "6.0"設定によりエラーなしで使い続けられるが、7.0 では完全に削除される - ts5to6 ツールにより、
baseUrl、rootDirなどの自動調整が可能 - TypeScript 7.0 は数か月以内にリリース予定で、Microsoft の内外にある大規模コードベースですでに広く採用が進んでいる
- ネイティブプレビュー nightly ビルド と VS Code 拡張 を通じてフィードバックを推奨
3件のコメント
Goベースのコンパイラへ完全に移行する時期が楽しみです!
えっ? TypeScript は将来的に Go ベースのネイティブ実装に変わるんですか?
コンパイラだけです