Node.jsでTypeScriptのenumが動かないとき|型除去の限界と実行方法

Node.jsの既定の型除去でenumが止まる理由と、版・構文・実行方法を確認する記事カバー
目次

結論:enumは既定の型除去だけでは実行できない

Node.js v24.19.0の組み込みTypeScript対応は、消してもJavaScriptとして成立する型構文を取り除く軽量機能です。enumは実行時の値を作るJavaScript生成が必要なため、既定のstrip-onlyではERR_UNSUPPORTED_TYPESCRIPT_SYNTAXになります。

小さい文字列enumならconstオブジェクトとas constへ書き換えます。既存enumの動作を保つなら通常コンパイルか対応ランナーを使います。tsconfig.jsonの変更だけでNode.jsがenumを変換することはありません。

1. Node.jsの版と最小例を確認する

node --version

この記事はv24.19.0の既定動作を基準にします。例は常にESモジュールになる.mtsを使います。.ctsはCommonJS、.tsは通常のパッケージ判定です。

state-enum.mtsを作ります。

enum TaskState {
  Waiting = "waiting",
  Done = "done",
}

function printState(state: TaskState): void {
  console.log(state);
}

printState(TaskState.Waiting);

既定の型除去で直接実行します。

node state-enum.mts

行番号などは環境で異なりますが、エラーの要点は次の形です。実測ログではなく、公式仕様に基づく説明用の想定例です。

ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX
TypeScript enum is not supported in strip-only mode
Node.jsの版確認からenumの書換えまたはコンパイルを選び、再実行するまでの5段階フロー
Node.jsの既定strip-onlyを基準に、enumで止まったときの選択肢を示す説明用フロー。 · 図を拡大

2. なぜ型注釈は消せてもenumは消せないのか

型エイリアスや型注釈は、削除してもJavaScriptとして成立します。

type UserId = string;
const id: UserId = "u-1";
console.log(id);

型部分を除けば次のJavaScriptが残ります。

const id = "u-1";
console.log(id);

一方、enumは実行時に参照するオブジェクトが必要です。概念的には次のようなコードを新たに生成しなければなりません。

var TaskState;
(function (TaskState) {
  TaskState["Waiting"] = "waiting";
  TaskState["Done"] = "done";
})(TaskState || (TaskState = {}));

既定の型除去は、このJavaScript生成を担当しません。

構文既定の型除去理由
型注釈、type、interface可能消してもJSが成立
enum不可実行時の値が必要
実行時コードを含むnamespace不可値や処理の生成が必要
型だけのnamespace可能実行時コードが残らない
parameter properties不可代入処理の生成が必要

3. 小さい文字列enumはconstオブジェクトへ書き換える

const TaskState = {
  Waiting: "waiting",
  Done: "done",
} as const;

type TaskState = (typeof TaskState)[keyof typeof TaskState];

function printState(state: TaskState): void {
  console.log(state);
}

printState(TaskState.Waiting);
node state-const.mts

想定される出力です。

waiting

as constや型定義は削除できるため、残りは有効なJavaScriptになります。ただし、数値enumの逆引きなど、enumの全動作を再現する一括置換ではありません。単純な文字列値の一覧に限って検討します。

4. 既存enumを維持するなら通常コンパイルか対応ランナーを使う

enumの意味を保つ場合は、TypeScriptコンパイラでJavaScriptを生成する方法が基本です。

npm install --save-dev typescript

src/state.mtsを対象にした構成例です。

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "outDir": "dist",
    "rootDir": "src",
    "strict": true,
    "noEmitOnError": true
  },
  "include": ["src/**/*.mts"]
}
npx tsc

.mtsから出力された.mjsを実行します。

node dist/state.mjs

開発中の直接実行には、Node.js公式資料が例示するtsxのような対応ランナーも使えます。

npm install --save-dev tsx
npx tsx src/state.mts

5. erasableSyntaxOnlyで実行前に見つける

TypeScript 5.8以降のerasableSyntaxOnlyは、enumなど実行時の意味を持つ構文をコンパイル時に検出します。Node.jsへ変換機能を追加する設定ではありません。

{
  "compilerOptions": {
    "noEmit": true,
    "target": "ESNext",
    "module": "NodeNext",
    "rewriteRelativeImportExtensions": true,
    "erasableSyntaxOnly": true,
    "verbatimModuleSyntax": true
  }
}
npx tsc --noEmit

verbatimModuleSyntaxは、型だけのimportをimport typeで明示し、importの自動除去に頼らないための設定です。enumを変換する機能ではありません。

よくある質問

tsconfig.jsonだけ直せばenumを実行できますか

できません。組み込み型除去はtsconfig.jsonを読みません。erasableSyntaxOnlyは問題を事前検出する設定です。

nodeで.tsや.mtsを直接実行すると型チェックもされますか

されません。型チェックが必要なら、別に次のコマンドなどを実行します。

npx tsc --noEmit

Node.js 24の--experimental-transform-typesは使えますか

v24.19.0の公式資料には、変換が必要な構文を扱う版依存の実験的選択肢として記載されています。

node --experimental-transform-types state-enum.mts

ただし、現行のNode.js 26系資料ではv26.0.0で削除されています。全版共通の解決策にはせず、使用中の版を確認してください。主な選択肢は書き換え、通常コンパイル、対応ランナーです。

関連記事

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次