Error [ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING]

ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING の直し方(node_modules の中の .ts は実行されない)

FIX SUMMARY verified
Applies when
node:24.18.0-alpinea dependency ships .ts as its entry point; Node deliberately does not type-strip under node_modules and no flag overrides it

Verified: reproduced in node:24.18.0-alpine, then the ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING signature was gone after the fix (exit 0).

node app.ts は動いていたのに、あるライブラリを import した瞬間に次のエラーで止まります。

Error [ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING]: Stripping types is currently unsupported
for files under node_modules, for "file:///app/node_modules/oldlib/index.ts"
    at stripTypeScriptModuleTypes (node:internal/modules/typescript:183:11)

自分の .ts の型注釈は問題なく消えていて、落ちているのは node_modules の中に入った瞬間です。エラーが示しているのは、依存ライブラリが .ts のまま公開されているという事実になります。

Node は node_modules の中だけ型を消しません

Node の型ストリッピングには、node_modules 配下は対象外という線が引かれています。あなたのプロジェクトの .ts は消しますが、インストールされたパッケージの .ts は消しません。

これは不具合ではなく、意図的な制限です。しかも理由は性能や技術的な都合ではありません。Node の公式ドキュメントは、こう書いています。

To discourage package authors from publishing packages written in TypeScript, Node.js refuses to handle TypeScript files inside folders under a node_modules path.

(パッケージ作者が TypeScript で書いたまま公開することを思いとどまらせるため、Node.js は node_modules 配下のフォルダにある TypeScript ファイルの処理を拒否します)

技術的にできないのではなく、やらないと決めている。だから、フラグで外す道も用意されていません。

フラグでは外せません

このエラーで最初に試したくなるのがフラグですが、どれも効きません

node --experimental-strip-types app.ts       # 同じエラー
node --experimental-transform-types app.ts   # 同じエラー

--experimental-transform-typesNode 26 で削除されており、そちらでは bad option になって起動すらしません。いずれにせよ、この制限は外せません。)

enum が拒否されるエラー(ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX)では --experimental-transform-types が効きますが、この制限には効きません

直し方:JavaScript を配っている版のライブラリを使う

直すべきは、あなたのコードでも Node の起動オプションでもありません。ライブラリの配り方です。

問題のあるパッケージは、こうなっています。

// node_modules/oldlib/package.json
{
  "main": "index.ts"     // .ts をそのまま公開している
}

正しく公開されているパッケージは、こうです。

// node_modules/oldlib/package.json
{
  "main": "index.js",       // 実行されるのはコンパイル済みの JavaScript
  "types": "index.d.ts"     // 型は型定義ファイルで提供する
}

変わるのは node_modules の中身だけで、自分のコードは 1 文字も触りません。

やることは、状況に応じて次のどれかです。

  • そのライブラリの新しい版を確認する。 ビルド成果物を公開するよう直っていることがあります。npm view <パッケージ名> versions で版を確認し、上げてみてください。
  • ライブラリに報告する。 .ts を直接公開するのは、Node で直接実行される前提だと成立しません(型定義ファイルを添えて JavaScript を配るのが通例です)。
  • 実行系を変える。 node で直接動かすのをやめ、バンドラや、.ts を変換できる実行系を通します。ただしこれは Node の型ストリッピングを使う方針そのものを降りる選択になります。

切り分け

  • 自分の .ts は動いていた → 正常です。制限は node_modules の中だけに効きます。エラーメッセージの for "file://..." の部分を読めば、どのファイルで止まったかが分かります。node_modules/ を含んでいれば、原因は依存ライブラリです。
  • エラーが ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX → 別のエラーです。そちらはファイルの場所ではなく、書かれている構文enum など)が原因です(Node 24 までなら --experimental-transform-types で動かせますが、26 ではそのフラグも消えています)。ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX の直し方 を参照してください。
  • エラーが ERR_UNKNOWN_FILE_EXTENSION: ".ts".ts の実行そのものができていません。Node の版が古い可能性があります。ERR_UNKNOWN_FILE_EXTENSION: “.ts” の直し方 を参照してください。
  • tsx では動いていたtsxnode_modules の中の .ts も変換します(同じ構成で動くことを確認しました)。Node の組み込みサポートは変換しないので、tsx から node に乗り換えた途端にこのエラーが出ますts-node については確認していません。
  • モノレポ(npm workspaces)で自作パッケージを参照しているこのエラーにはなりません。 npm workspaces は node_modules/<パッケージ名>packages/<名前> へのシンボリックリンクとして張り、Node は実体のパスを見ます。実体は node_modules の外にあるので、制限に当たりません(.ts のまま参照して動くことを確認しました)。自作パッケージが node_modules実体として置かれる構成(依存として npm install した場合など)では、外部ライブラリと同じ扱いになります。

検証環境

  • node:24.18.0-alpine、ネットワーク無し
  • 再現:node_modules/oldlib"main": "index.ts" として .ts を公開している状態で node app.ts を実行し、ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING が出て終了コード 1
  • 修正:app.ts は 1 文字も変えずnode_modules/oldlib"main": "index.js""types": "index.d.ts" に差し替えるだけで終了コード 0・シグネチャ消滅
  • --experimental-strip-types でも --experimental-transform-types でも同じエラーになる」「Node 22.18.0 / 24.18.0 / 26.5.0 のいずれでも同じ」「Node 26.5.0 では --experimental-transform-typesbad option になる」ことは、それぞれ実行して確認しました
  • 「npm workspaces のシンボリックリンク経由では、.ts のまま参照しても動く」「tsxnode_modules の中の .ts を変換して実行できる」も、同じ構成で確認しました

Node が node_modules 配下を対象外にしている理由は、Node 公式ドキュメント(Modules: TypeScript)の記述によります(実測ではありません)。ts-node / バンドラ / カスタムローダで回避できるかどうかは確認していません(tsx は上記のとおり確認しました)。エラーメッセージの currently という語は Node 側の文言であり、この制限が将来変わるかどうかも確認していません。

検証(machine-verified)

この修正は node:24.18.0-alpine のバージョン固定コンテナ内で再現し、修正後に ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING のシグネチャが消えることを機械で確認しています。

verify — run-case.mjs
$ node run-case.mjs node/node-modules-type-stripping
● reproduce ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING present ✓
● apply fix exit 0
● re-run ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING gone ✓
PASS verified · node:24.18.0-alpine · signature gone