この記事はすきま経営からの転載です。
結論から書く。Node.js 22系(--experimental-strip-types、22.6以降で利用可能)でTypeScriptをそのまま実行できるようになったことで、私は複数のプロジェクトからts-nodeとtsxを削除した。ビルドステップを挟まない小〜中規模のスクリプト用途に限れば、もう型ストリップ専用のランタイムを別途インストールする理由がない。今回はどのツールをどう置き換えたか、そして置き換えなかったものは何かを具体的に書く。
そもそも何が起きているのか
Node.js 22.6で--experimental-strip-typesフラグが入り、Node.js自身が.tsファイルの型注釈を実行前に取り除いて実行できるようになった。これは「TypeScriptをコンパイルしている」のではなく「型注釈だけを剥がしてJavaScriptとして流す」という割り切った実装で、enumやnamespaceのようなJavaScriptに存在しない構文には対応していない(Node.js 23以降で段階的に拡張されている)。
裏を返すと、型注釈だけを剥がせば動く程度のシンプルなTypeScript——スクリプト、CLIツール、Node.js単体で完結するバッチ処理——であれば、ビルドツールを挟まずNode.js本体だけで完結する。私がすきま経営ブログの運用で使っているWordPress同期スクリプト(scripts/lib/wp-sync.ts)は、まさにこのユースケースだった。
捨てたツール1: ts-node
以前は個人プロジェクトの小さなスクリプトでもts-nodeをdevDependenciesに入れてts-node script.tsのように実行していた。だがts-nodeはフルのTypeScriptコンパイラを内部で回すため、初回実行が体感で待たされることが多く、tsconfig.jsonの設定次第で挙動が変わる不安定さもあった。
Node.js 22のネイティブ実行に切り替えてからは、package.jsonのスクリプトを次のように書き換えている。
{
"scripts": {
"sync": "node --experimental-strip-types scripts/lib/wp-sync.ts"
}
}
ts-nodeをアンインストールし、tsconfig.jsonからts-node固有の設定セクションを削った。依存パッケージが1つ減るだけでも、npm installの時間とlockfileの差分が減るので地味に効く。
捨てたツール2: tsx(の一部用途)
tsxはts-nodeより高速で愛用していたが、これも「Node.js単体で動く型注釈のみのスクリプト」に関しては置き換えた。具体的には、WordPress下書き同期のようにクリーンアーキテクチャで書いたスクリプト(domain/ports/adapters/usecase構成)で、外部の複雑な型機能を使っていないものが対象になる。
一方でtsxを完全に手放したわけではない。監視モード(tsx watch)を使う開発中のデバッグや、パスエイリアス(tsconfig.jsonのpaths)に依存したコードは、まだネイティブ実行だけでは完結しない場面がある。この見極めが今回一番実務的に効いた判断だった。
どこまでネイティブ実行に寄せるか、判断基準
すべてのプロジェクトでツールを剥がしたわけではない。私が実際に使っている判断基準は次の通りだ。
- Node.js単体で完結するか: ブラウザ向けバンドルやフロントエンドのビルドが絡む場合はViteやesbuildが必要なので対象外
-
enum・namespace・パスエイリアスを使っていないか: 使っている場合は型ストリップだけでは動かない、または動いても意図と違う挙動になる - CI・本番実行環境がNode.js 22以上か: GitHub Actionsのランナーやデプロイ先のNode.jsバージョンを先に確認する。22未満の環境が1つでも残っていれば、フラグ付き実行に統一できない
-
チームで使うか個人スクリプトか: 複数人が触るリポジトリでは
--experimental-strip-typesという「experimental」の文字が心理的ハードルになる。今のところ個人運用のスクリプト(wp-syncのようなもの)から先行導入している
この基準に照らして、すきま経営ブログのWordPress同期スクリプトとaerial-earth-studioの一部バッチ処理は対象にしたが、フロントエンド込みのプロジェクトやチーム開発中のリポジトリはtsxのまま維持している。
捨てなかったもの: tscによる型チェック
ここは誤解されやすいので明確に書いておく。Node.js 22のネイティブTypeScript実行は「型を剥がして実行する」だけで、型チェックはしない。型エラーがあってもそのまま実行されてしまう。
そのためtsc --noEmitによるビルド前の型チェックはCIから外していない。実行系のツールを剥がしたのはあくまで「ローカルやCIでスクリプトを走らせる」レイヤーの話で、「型の正しさを検証する」レイヤーは従来通りtscに任せている。この2つを混同すると、型エラーに気づけないまま本番で実行してしまうリスクがある。
まとめ
- Node.js 22の
--experimental-strip-typesで、型注釈だけのシンプルなTypeScriptスクリプトはNode.js単体で実行できるようになった -
ts-nodeは個人プロジェクトから完全に削除した。tsxは監視モードやパスエイリアス依存のコードでは併用を継続している - 置き換えの判断基準は「Node.js単体で完結するか」「特殊構文を使っていないか」「実行環境のNode.jsバージョン」「個人利用かチーム利用か」の4点
- 型チェック(
tsc --noEmit)は型ストリップとは別レイヤーなので、CIから外さず維持している
次回は、この判断基準を実際に適用してwp-syncスクリプトの依存を整理した際の、具体的なbefore/afterを書く予定だ。