Back

Node.jsでTypeScriptをネイティブ実行する方法

Node.jsでTypeScriptをネイティブ実行する方法

Node.js 23.6.0は、TypeScript開発者にとって転換点となります。ts-nodeやtscなどのトランスパイルツールを使わずに、.tsファイルを直接実行できるようになりました。このネイティブTypeScriptサポートにより、ビルドステップを排除しながら、IDE経由でタイプセーフティを維持することで、開発ワークフローが合理化されます。

このガイドでは、基本的なセットアップから本番環境での考慮事項まで、Node.jsでTypeScriptをネイティブ実行するために必要なすべてを網羅します。型除去(type stripping)の仕組み、サポートされるTypeScript機能、プロジェクトを最適な互換性で設定する方法を学習できます。

重要なポイント

  • Node.js 23.6.0はトランスパイレーションなしでTypeScriptファイルを直接実行
  • 型除去により、コード構造を保持しながら型注釈を削除
  • 一般的なTypeScript機能の大部分が動作するが、enumsとnamespaceには回避策が必要
  • import文には.ts拡張子を含める必要がある
  • ネイティブ実行により、従来ツールと比較して2〜3倍高速な起動時間を実現

クイックスタート: Node.js 23.6.0でTypeScriptを実行

ネイティブ実行を実証するために、シンプルなTypeScriptファイルから始めましょう:

// greeting.ts
function greet(name: string): string {
  return `Hello, ${name}!`
}

console.log(greet("TypeScript"))

Node.js 23.6.0以降では、これを直接実行できます:

node greeting.ts

以上です—コンパイルステップは不要です。Node.jsが型注釈を除去して、残りのJavaScriptを実行します。

Node.jsのバージョンを確認するには:

node --version  # v23.6.0以上である必要があります

初回実行時に実験的機能の警告が表示されます:

ExperimentalWarning: Type Stripping is an experimental feature and might change at any time

開発時にこの警告を抑制するには:

node --disable-warning=ExperimentalWarning greeting.ts

または永続的に設定:

export NODE_OPTIONS="--disable-warning=ExperimentalWarning"

Node.jsにおける型除去の理解

型除去は、従来のTypeScriptトランスパイレーションとは根本的に異なります。TypeScriptをJavaScriptに変換するのではなく、Node.jsは元のコード構造を保持しながら型注釈を単純に削除します。

型除去中に発生する処理は以下の通りです:

// 元のTypeScript
function calculate(a: number, b: number): number {
  return a + b
}

// 型除去後(Node.jsが実行するもの)
function calculate(a        , b        )         {
  return a + b
}

空白の保持に注目してください—これにより、ソースマップを必要とせずに、デバッグ用の正確な行番号が維持されます。

パフォーマンス上の利点

ネイティブTypeScript実行は、大幅なパフォーマンス向上を提供します:

  • トランスパイレーションオーバーヘッドなし: 中間ステップなしの直接実行
  • 高速起動時間: ts-nodeの120msに対して約45ms
  • メモリ使用量削減: メモリにトランスパイラーが読み込まれない
  • 簡素化されたデバッグ: 元の行番号が保持される

Node.jsにおけるTypeScriptサポートの進化

進化を理解することで、適切なアプローチを選択できます:

v22.6.0: 初期型除去

node --experimental-strip-types app.ts

基本的な型削除のみ—TypeScript固有の構文サポートなし。

v22.7.0: 型変換

node --experimental-transform-types app.ts

変換によるenumsとnamespaceのサポートを追加。

v23.6.0: デフォルト型除去

node app.ts  # 型除去がデフォルトで有効

基本的なTypeScript実行にフラグは不要。

サポートされるTypeScript機能と制限事項

動作するもの

Node.jsのネイティブTypeScriptは、日常的なTypeScript機能の大部分をサポートします:

// ✅ 型注釈
let count: number = 0

// ✅ インターフェース
interface User {
  id: number
  name: string
}

// ✅ 型エイリアス
type Status = 'active' | 'inactive'

// ✅ ジェネリクス
function identity<T>(value: T): T {
  return value
}

// ✅ 型インポート
import type { Config } from './types.ts'

動作しないもの

一部のTypeScript固有機能には回避策が必要です:

機能サポート回避策
Enumsユニオン型またはconstオブジェクトを使用
NamespacesESモジュールを使用
パラメータープロパティ明示的なプロパティ宣言
JSX/TSX従来のトランスパイレーションを使用
デコレーターV8サポートを待つ

回避策の例:

// ❌ Enum(サポートされていない)
enum Status {
  Active,
  Inactive
}

// ✅ ユニオン型の代替
type Status = 'active' | 'inactive'

// ✅ constオブジェクトの代替
const Status = {
  Active: 'active',
  Inactive: 'inactive'
} as const

ファイル拡張子とモジュールシステム

Node.jsはファイル拡張子を使用してモジュール処理を決定します:

  • .ts - package.jsonの"type"フィールドに従う(ESMまたはCommonJS)
  • .mts - 常にESMとして扱われる
  • .cts - 常にCommonJSとして扱われる

重要:ローカルインポートには.ts拡張子を含める必要があります:

// ❌ 従来のTypeScript
import { utils } from './utils'

// ✅ Node.jsネイティブTypeScript
import { utils } from './utils.ts'

ネイティブTypeScript用のtsconfig.json設定

Node.jsは実行時にtsconfig.jsonを読み取りませんが、適切な設定によりIDEサポートと型チェックが確保されます:

{
  "compilerOptions": {
    "target": "esnext",
    "module": "nodenext",
    "moduleResolution": "nodenext",
    "allowImportingTsExtensions": true,
    "rewriteRelativeImportExtensions": false,
    "verbatimModuleSyntax": true,
    "strict": true,
    "noEmit": true
  }
}

主要設定の説明:

  • allowImportingTsExtensions: インポートパスでの.tsを許可
  • rewriteRelativeImportExtensions: .ts拡張子を保持するためfalseに設定
  • verbatimModuleSyntax: 明示的な型インポートを強制
  • noEmit: 意図しないJavaScript生成を防止

型チェックを別途実行:

tsc --noEmit

従来のTypeScriptツールからの移行ガイド

ts-nodeからの移行

  1. ts-node依存関係を削除:
npm uninstall ts-node
  1. package.jsonスクリプトを更新:
// 変更前
"scripts": {
  "dev": "ts-node src/index.ts"
}

// 変更後
"scripts": {
  "dev": "node src/index.ts"
}
  1. サポートされていない機能を処理(enumsをunionsに変換)

tscコンパイルからの移行

  1. ビルドステップを削除:
// これらのスクリプトを削除
"scripts": {
  "build": "tsc",
  "start": "node dist/index.js"
}

// 代わりにこれを使用
"scripts": {
  "start": "node src/index.ts"
}
  1. CI/CDパイプラインを更新してコンパイルをスキップ

パフォーマンス比較

ネイティブTypeScript実行は大幅な改善を示します:

指標ネイティブTypeScriptts-nodetsc + node
起動時間約45ms約120ms約200ms
メモリ使用量ベースライン+30MB+10MB
ビルドステップなしなし必要

よくある落とし穴と解決策

インポートパスエラー

// エラー: Cannot find module './utils'
import { helper } from './utils'

// 解決策: .ts拡張子を含める
import { helper } from './utils.ts'

サポートされていない構文

// エラー: Enums are not supported
enum Color { Red, Blue }

// 解決策: constオブジェクトを使用
const Color = { Red: 0, Blue: 1 } as const

型チェックの混同

覚えておいてください:Node.jsは型チェックを実行しません。型検証には常にtsc --noEmitを実行してください。

本番環境での考慮事項

ネイティブTypeScriptを使用すべき場合

  • 開発環境
  • プロトタイプと実験
  • 小規模スクリプトとユーティリティ
  • 実験的機能に対応できるチーム

避けるべき場合

  • 本番アプリケーション(安定版まで)
  • 完全なTypeScript機能が必要なプロジェクト
  • 安定したツールが必要なチーム
  • 複雑なビルドパイプライン

Docker調整

# 変更前
FROM node:23-alpine
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
CMD ["node", "dist/index.js"]

# 変更後
FROM node:23-alpine
COPY package*.json ./
RUN npm ci
COPY . .
CMD ["node", "src/index.ts"]

結論

Node.js 23.6.0のネイティブTypeScriptサポートは、開発ワークフローの大幅な簡素化を表しています。トランスパイレーションステップを排除することで、ビルドツールの設定よりもコード記述に集中できます。TypeScript固有の構文に関する制限は存在しますが、ほとんどの開発シナリオにおける利点は魅力的です。

まず開発環境でネイティブTypeScriptを試し、既存プロジェクトを段階的に移行し、TypeScriptがJavaScriptが動作するあらゆる場所で実行される未来に備えましょう。この機能が安定化するにつれて、より広範な採用と今後のNode.jsリリースでの機能拡張が期待されます。

よくある質問

技術的には可能ですが、本番使用はまだ推奨されません。この機能はまだ実験的であり、変更される可能性があります。開発環境、プロトタイプ、重要でないアプリケーションで使用してください。本番環境では、機能が安定するまで従来のトランスパイレーションを継続使用してください。

はい、型チェックのためにTypeScriptを開発依存関係として保持すべきです。Node.jsは型を検証せずに除去するだけです。開発中またはCIパイプラインで型エラーを捕捉するために、tsc --noEmitを別途実行してください。

ネイティブTypeScriptでは、従来のTypeScriptツールとは異なり、インポートパスに明示的な.ts拡張子が必要です。すべてのローカルインポートを'./module'から'./module.ts'に更新してください。外部パッケージのインポートには拡張子は不要です。

シンプルなケースではenumsをユニオン型に、数値enumsではas constアサーション付きのconstオブジェクトに置き換えてください。文字列enumsの場合、ユニオン型が完璧に動作します。このアプローチは実際により木揺らし(tree-shakeable)に優しく、現代のTypeScriptプラクティスとよく合致します。

Node.jsチームは、パフォーマンス上の理由から完全なトランスパイレーションではなく型除去に焦点を当てています。enumsやデコレーターなどのランタイム変換が必要な機能は、V8がネイティブに実装する際にサポートを得る可能性がありますが、目標は完全なTypeScript互換性ではなく、高速で最小限の処理です。

Complete picture for complete understanding

Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Check our GitHub repo and join the thousands of developers in our community.

OpenReplay