TypeScriptをNode.jsで実行する方法は、「nodeにそのまま渡す(型ストリップ)」「tsx」「ts-node」「tscでJavaScriptにしてからnode」の4通りです。いまのNode.jsは、型の注釈を取り除くだけで動くコードなら、追加の道具なしで node ファイル名.ts と打つだけで実行できます。 型ストリップ(type stripping)とは、型の注釈を空白に置き換えて、残りをそのままJavaScriptとして動かす仕組みのことです。

確認環境:Ubuntu 24.04、Node.js 22.22.2 と 24.21.0、TypeScript 7.0.2(tsc)、tsx 4.23.15、ts-node 10.9.2(TypeScript 6.0.3 と組み合わせ)、@types/node 22.20.5。この記事では、同じ10個のファイルを4通りの方法で動かし、表示された結果とエラー文をそのまま載せます。出力に出てくるフォルダのパスは /home/taro/app に置き換えて表示しています。

TypeScriptをNode.jsで実行する方法の早見表

4通りの方法

方法 コマンド 追加で入れるもの 型チェック 向いている用途
node で直接実行(型ストリップ) node src/main.ts なし しない スクリプト、小さなツール、新しく作るサーバー
tsx npx tsx src/main.ts tsx しない enum やパスエイリアスを使う既存のコード、開発中の実行
ts-node npx ts-node src/main.ts ts-node、typescript 6 系 する 実行のたびに型も確かめたい CommonJS のコード
tsc のあと node npx tsc && node dist/main.js typescript する(tsc が担当) 配布するパッケージ、本番で動かすビルド

書き方ごとの結果(Node.js 22.22.2 と 24.21.0 で同じ結果)

書き方 node 直接 tsx ts-node(ESM) tsc のあと node
型注釈・interface だけ 動く 動く 動く 動く
enum ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX 動く 動く 動く
namespace(値を含む) ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX 動く 動く 動く
パラメータプロパティ ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX 動く 動く 動く
パスエイリアス(@/lib/add.js) ERR_MODULE_NOT_FOUND 動く Cannot find package tsc は通るが node で ERR_MODULE_NOT_FOUND
拡張子なし import(./lib/add) ERR_MODULE_NOT_FOUND 動く Cannot find module tsc が TS2835
拡張子 .ts の import 動く 動く 動く 動く(.js に書き換えて出力)
拡張子 .js の import ERR_MODULE_NOT_FOUND 動く 動く 動く
JSX(.tsx) ERR_UNKNOWN_FILE_EXTENSION 動く 動く 動く
type を付けない型の import SyntaxError 動く 動く 動く
型エラーのあるコード 動く(型は見ない) 動く(型は見ない) 止まる tsc が TS2322 を表示

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「TypeScriptをNode.jsで実行|tsx・ts-node・型ストリップ」

確認に使ったファイルと設定

package.json には "type": "module" を指定し、tsconfig.json は次の内容にしました。

{
  "compilerOptions": {
    "target": "es2022",
    "module": "nodenext",
    "strict": true,
    "types": ["node"],
    "rootDir": "./src",
    "outDir": "./dist",
    "jsx": "react",
    "paths": { "@/*": ["./src/*"] },
    "allowImportingTsExtensions": true,
    "rewriteRelativeImportExtensions": true
  }
}

主なファイルは次のとおりです。

// src/lib/add.ts
export function add(a: number, b: number): number {
  return a + b;
}
// src/basic.ts(型注釈・interface だけ)
interface Task {
  id: number;
  title: string;
}

const task: Task = { id: 1, title: "備品の発注" };
console.log(`basic: ${task.id} ${task.title}`);
// src/enum.ts
enum Status {
  Todo,
  Done,
}

console.log(`enum: ${Status.Done} ${Status[1]}`);
// src/namespace.ts
namespace Tax {
  export const rate = 0.1;
  export function withTax(price: number): number {
    return Math.round(price * (1 + rate));
  }
}

console.log(`namespace: ${Tax.withTax(1000)}`);
// src/param-prop.ts(パラメータプロパティ)
class Member {
  constructor(private readonly name: string) {}
  hello(): string {
    return `こんにちは、${this.name}さん`;
  }
}

console.log(`param-prop: ${new Member("佐藤").hello()}`);
// src/alias.ts(パスエイリアス)
import { add } from "@/lib/add.js";

console.log(`alias: ${add(1, 2)}`);
// src/noext.ts(拡張子なし)。ext-ts.ts は "./lib/add.ts"、ext-js.ts は "./lib/add.js" と書いたもの
import { add } from "./lib/add";

console.log(`noext: ${add(1, 2)}`);
// src/typeerror.ts(型エラー)
const count: number = "3";
console.log(`typeerror: ${count}`);
// src/view.tsx(JSX。自作の関数 h で文字列を組み立てる)
/** @jsx h */
function h(tag: string, props: Record<string, unknown> | null, ...children: unknown[]): string {
  const attrs = Object.entries(props ?? {}).map(([k, v]) => ` ${k}="${v}"`).join("");
  return `<${tag}${attrs}>${children.join("")}</${tag}>`;
}

declare global {
  namespace JSX {
    type Element = string;
    interface IntrinsicElements {
      [name: string]: Record<string, unknown>;
    }
  }
}

const view = <p class="note">jsx: ok</p>;
console.log(view);

方法1:nodeで直接実行する(型ストリップ)

node src/basic.ts
basic: 1 備品の発注

Node.js 22.22.2 と 24.21.0 のどちらも、フラグなし・警告なしでこの結果になりました。Node.js の公式ドキュメントによると、経緯は次のとおりです。

Node.js の版 型ストリップの扱い(公式ドキュメントの記載)
22.7.0 --experimental-transform-types フラグを追加
22.18.0 以降 フラグなしで有効(それより前は --experimental-strip-types を付ける)
23.6.0 フラグなしで有効
24.3.0 実験的機能の警告を表示しなくなった
24.12.0 安定版(Stable)になった

型を取り除くだけでは動かない構文

型ストリップは「消すだけ」なので、JavaScript のコードを新しく作る必要がある構文は扱えません。enum を渡したときの出力です(at で始まる行は省略)。

node src/enum.ts
file:///home/taro/app/src/enum.ts:1
  > enum Status {
      Todo,
      Done,
  > }

SyntaxError [ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX]: TypeScript enum is not supported in strip-only mode
…(省略)…
  code: 'ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX'
}

Node.js v22.22.2
ファイル エラー文(22.22.2 と 24.21.0 で同じ)
enum.ts SyntaxError [ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX]: TypeScript enum is not supported in strip-only mode
namespace.ts SyntaxError [ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX]: TypeScript namespace declaration is not supported in strip-only mode
param-prop.ts SyntaxError [ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX]: TypeScript parameter property is not supported in strip-only mode
view.tsx TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".tsx" for /home/taro/app/src/view.tsx

importは「.ts を付ける」「型には type を付ける」

Node.js は tsconfig.json を読まないので、import は実際のファイル名どおりに書きます。

import の書き方 結果 エラー文
"./lib/add.ts" 動く(ext-ts: 3) —
"./lib/add" 止まる Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/home/taro/app/src/lib/add' imported from /home/taro/app/src/noext.ts
"./lib/add.js" 止まる Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/home/taro/app/src/lib/add.js' imported from /home/taro/app/src/ext-js.ts
"@/lib/add.js"(パスエイリアス) 止まる Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@/lib' imported from /home/taro/app/src/alias.ts

もう1つ、型を import するときの書き方にも決まりがあります。interface と値の両方を export しているファイルを用意しました。

// src/lib/types.ts
export interface Task {
  id: number;
  title: string;
}
export const defaultTitle = "無題";
// src/import-type-ng.ts
import { Task, defaultTitle } from "./lib/types.ts";

const task: Task = { id: 1, title: defaultTitle };
console.log(`import: ${task.title}`);
file:///home/taro/app/src/import-type-ng.ts:1
import { Task, defaultTitle } from "./lib/types.ts";
         ^^^^
SyntaxError: The requested module './lib/types.ts' does not provide an export named 'Task'

Node.js v22.22.2

Task は型なので、実行時には存在しません。型の import には type を付けます。 type が付いた部分は、型ストリップで取り除かれます。

// src/import-type-ok.ts
import { type Task, defaultTitle } from "./lib/types.ts";
import: 無題

--experimental-transform-typesでenumなども動かす

--experimental-transform-types を付けると、Node.js が enum などを JavaScript に変換してから動かします。

node --experimental-transform-types src/enum.ts
enum: 1 Done
(node:31201) ExperimentalWarning: Transform Types is an experimental feature and might change at any time
ファイル フラグなし --experimental-transform-types 付き
enum.ts 止まる enum: 1 Done
namespace.ts 止まる namespace: 1100
param-prop.ts 止まる param-prop: こんにちは、佐藤さん
alias.ts 止まる 止まる(Cannot find package '@/lib')
noext.ts / ext-js.ts 止まる 止まる(ERR_MODULE_NOT_FOUND)
view.tsx 止まる 止まる(ERR_UNKNOWN_FILE_EXTENSION)
import-type-ng.ts 止まる 止まる(does not provide an export named 'Task')

変わるのは構文の変換だけで、import の決まりと .tsx の扱いは同じです。24.21.0 でも実験的機能の警告が表示されました。

node_modulesの中の.tsは実行されない

node_modules の中に .ts を入口にしたパッケージを置いて import すると、次のエラーになりました。

Error [ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING]: Stripping types is currently unsupported for files under node_modules, for "file:///home/taro/app/node_modules/demo-pkg/index.ts"

公式ドキュメントにも、node_modules 配下の TypeScript ファイルは扱わないと書かれています。パッケージとして配るコードは、tsc で .js にしてから公開します。

erasableSyntaxOnlyで「消すだけで動く書き方」にそろえる

実行する前に気づけるように、tsc の erasableSyntaxOnly を有効にして、型チェックの段階で知らせてもらいます。

npx tsc --noEmit --erasableSyntaxOnly
src/enum.ts(1,6): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
src/namespace.ts(1,11): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
src/param-prop.ts(2,15): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.

--locale ja を付けたときの文面です。

src/enum.ts(1,6): error TS1294: 'erasableSyntaxOnly' が有効な場合、この構文は使用できません。
src/namespace.ts(1,11): error TS1294: 'erasableSyntaxOnly' が有効な場合、この構文は使用できません。
src/param-prop.ts(2,15): error TS1294: 'erasableSyntaxOnly' が有効な場合、この構文は使用できません。

(同じ実行で、noext.ts の TS2835 と typeerror.ts の TS2322 も表示されます。ここでは TS1294 の行だけを抜き出しました。)

書き換え例:enum → as const のオブジェクト

// 直す前
enum Status {
  Todo,
  Done,
}
// 直したあと(src/erasable/enum.ts)
const Status = {
  Todo: 0,
  Done: 1,
} as const;
type Status = (typeof Status)[keyof typeof Status];

const current: Status = Status.Done;
console.log(`enum: ${current}`);
enum: 1

書き換え例:namespace → ふつうの関数とオブジェクト

// 直したあと(src/erasable/namespace.ts)
const rate = 0.1;
function withTax(price: number): number {
  return Math.round(price * (1 + rate));
}
export const Tax = { rate, withTax };

console.log(`namespace: ${Tax.withTax(1000)}`);
namespace: 1100

書き換え例:パラメータプロパティ → フィールド宣言と代入

// 直したあと(src/erasable/param-prop.ts)
class Member {
  private readonly name: string;
  constructor(name: string) {
    this.name = name;
  }
  hello(): string {
    return `こんにちは、${this.name}さん`;
  }
}

console.log(`param-prop: ${new Member("佐藤").hello()}`);
param-prop: こんにちは、佐藤さん

3つとも、Node.js 22.22.2 と 24.21.0 でフラグなしで動きました。

nodeで直接実行するときのtsconfig.json

Node.js の公式ドキュメントは、TypeScript 5.8 以降と、noEmit・target esnext・module nodenext・rewriteRelativeImportExtensions・erasableSyntaxOnly・verbatimModuleSyntax の組み合わせをすすめています。これに strict などを足して、次の設定で確かめました。

{
  "compilerOptions": {
    "target": "esnext",
    "module": "nodenext",
    "strict": true,
    "types": ["node"],
    "noEmit": true,
    "erasableSyntaxOnly": true,
    "verbatimModuleSyntax": true,
    "allowImportingTsExtensions": true,
    "rewriteRelativeImportExtensions": true
  },
  "include": ["src"]
}

verbatimModuleSyntax を有効にすると、type を付け忘れた import も tsc が見つけてくれます。

src/import-type-ng.ts(1,10): error TS1484: 'Task' is a type and must be imported using a type-only import when 'verbatimModuleSyntax' is enabled.
src/import-type-ng.ts(1,10): error TS1484: 'Task' は型であり、'verbatimModuleSyntax' が有効であるときは、型のみのインポートを使用してインポートされる必要があります。
オプション 役割 見つけてくれるもの
erasableSyntaxOnly 消すだけでは動かない構文をエラーにする enum、namespace、パラメータプロパティ(TS1294)
verbatimModuleSyntax import / export を書いたとおりに扱う type の付け忘れ(TS1484)
allowImportingTsExtensions import に .ts を書けるようにする —
rewriteRelativeImportExtensions tsc で出力するとき、相対パスの .ts を .js に書き換える —
noEmit 出力せず、型チェックだけ行う —

方法2:tsxで実行する

npm install --save-dev tsx
npx tsx src/enum.ts
enum: 1 Done

用意した10個のファイルは、tsx 4.23.15 ではすべて動きました(Node.js 22.22.2 と 24.21.0 の両方)。

ファイル tsx の出力
basic.ts basic: 1 備品の発注
enum.ts enum: 1 Done
namespace.ts namespace: 1100
param-prop.ts param-prop: こんにちは、佐藤さん
alias.ts(tsconfig.json の paths を使う) alias: 3
noext.ts / ext-ts.ts / ext-js.ts noext: 3 / ext-ts: 3 / ext-js: 3
view.tsx JSX が h の呼び出しに変換され、p 要素の文字列が表示された
import-type-ng.ts(type なし) import: 無題
typeerror.ts typeerror: 3

tsx は型チェックをしません。 typeerror.ts は、number と注釈した変数に文字列を入れていますが、そのまま実行されました。型の確認は npx tsc --noEmit と組み合わせます。

方法3:ts-nodeで実行する

ts-node は、TypeScript 本体の API を使って変換と型チェックを行います。そのため、組み合わせる typescript の版が結果を左右します。

TypeScript 7.0.2とは組み合わせられない

typescript 7.0.2 と ts-node 10.9.2 を同じフォルダに入れて実行した結果です。

npx ts-node src/basic.ts
/home/taro/app/node_modules/ts-node/dist/configuration.js:91
    const { fileExists = ts.sys.fileExists, readFile = ts.sys.readFile, skipProject = index_1.DEFAULTS.skipProject, project = index_1.DEFAULTS.project, tsTrace = index_1.DEFAULTS.tsTrace, } = rawApiOptions;
                                ^

TypeError: Cannot read properties of undefined (reading 'fileExists')

TypeScript 7.0 には、プログラムから呼ぶための API が入っていません。ts-node を使うフォルダには、typescript の 6 系を入れます。 以降は TypeScript 6.0.3 との組み合わせです。

ESMのプロジェクト:"type": "module" のとき

package.json に "type": "module" があるフォルダで npx ts-node src/enum.ts と打つと、次のエラーになりました。

SyntaxError: TypeScript enum is not supported in strip-only mode

これは Node.js の型ストリップのエラー文です。つまり、この打ち方では Node.js 自身が .ts を処理していました。ts-node に処理させるには、ローダーとして指定します。

node --loader ts-node/esm src/enum.ts
(node:403) ExperimentalWarning: `--experimental-loader` may be removed in the future; instead use `register()`:
…(省略)…
enum: 1 Done
ファイル node --loader ts-node/esm の結果
basic / enum / namespace / param-prop 動く
ext-ts.ts / ext-js.ts / view.tsx / import-type-ng.ts 動く
alias.ts Error: Cannot find package '@/lib' imported from /home/taro/app/src/alias.ts
noext.ts Error: Cannot find module '/home/taro/app/src/lib/add' imported from /home/taro/app/src/noext.ts
typeerror.ts 止まる(実行されず、エラーの中身は表示されなかった)

CommonJSのプロジェクト:"type" を書かないとき

package.json から type を外し、tsconfig.json を "module": "commonjs", "moduleResolution": "bundler" に変えたフォルダでは、npx ts-node ファイル名 の形で ts-node が処理しました。

ファイル npx ts-node の結果
basic / enum / namespace / param-prop 動く
noext.ts 動く(noext: 3)
view.tsx 動く(ファイル末尾に export {}; を足してモジュール扱いにした場合)
alias.ts Error: Cannot find module '@/lib/add.js'
ext-ts.ts / ext-js.ts Error: Cannot find module './lib/add.js'
typeerror.ts 型エラーを表示して止まる

型エラーのときの出力です。

TSError: ⨯ Unable to compile TypeScript:
src/typeerror.ts(1,7): error TS2322: Type 'string' is not assignable to type 'number'.

  diagnosticCodes: [ 2322 ]
}

実行のたびに型エラーで止めてくれるのが、ts-node の特徴です。 型チェックを省いて速く動かしたいときは --transpile-only を付けます(typeerror: 3 と表示されました)。

方法4:tscでJavaScriptにしてからnodeで実行する

npx tsc
node dist/enum.js
enum: 1 Done

tsc は、enum やパラメータプロパティを JavaScript のコードに変換します。dist/enum.js と dist/param-prop.js の中身です。

var Status;
(function (Status) {
    Status[Status["Todo"] = 0] = "Todo";
    Status[Status["Done"] = 1] = "Done";
})(Status || (Status = {}));
console.log(`enum: ${Status.Done} ${Status[1]}`);
export {};
class Member {
    name;
    constructor(name) {
        this.name = name;
    }
    hello() {
        return `こんにちは、${this.name}さん`;
    }
}
console.log(`param-prop: ${new Member("佐藤").hello()}`);
export {};

10個のファイルをまとめて tsc にかけたときの出力は、次の2行でした。

src/noext.ts(1,21): error TS2835: Relative import paths need explicit file extensions in ECMAScript imports when '--moduleResolution' is 'node16' or 'nodenext'. Did you mean './lib/add.js'?
src/typeerror.ts(1,7): error TS2322: Type 'string' is not assignable to type 'number'.
ファイル tsc node dist/…
basic / enum / namespace / param-prop / view 通る 動く
ext-ts.ts 通る(import を "./lib/add.js" に書き換えて出力) 動く
ext-js.ts 通る 動く
import-type-ng.ts 通る(Task の import を取り除いて出力) 動く
noext.ts TS2835 Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/home/taro/app/dist/lib/add' imported from /home/taro/app/dist/noext.js
alias.ts 通る("@/lib/add.js" のまま出力) Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@/lib' imported from /home/taro/app/dist/alias.js
typeerror.ts TS2322(.js は出力される) 動く(typeerror: 3)

paths は型チェックのための設定で、tsc は出力する import を書き換えません。 パスエイリアスを使うコードを tsc の出力のまま node で動かすときは、相対パスで書くのが確実です。

用途別の選び方早見表

やりたいこと 選ぶ方法 理由
新しく書くスクリプトやツールを、道具を増やさずに動かす node で直接実行 追加のインストールなし。erasableSyntaxOnly で書き方をそろえられる
enum・namespace・パラメータプロパティを使っているコードを、そのまま動かす tsx 10個のファイルがすべて動いた
tsconfig.json の paths(@/ など)を使っている tsx 4通りのうち、パスエイリアスを解決できたのは tsx だけだった
.tsx(JSX)を Node.js で動かす tsx か、tsc のあと node node 直接では .tsx が ERR_UNKNOWN_FILE_EXTENSION になる
実行のたびに型エラーで止めたい ts-node(CommonJS、TypeScript 6 系) TS2322 を表示して止まった
TypeScript 7 の tsc を使っている node 直接 か tsx + tsc --noEmit ts-node 10.9.2 は 7.0.2 と組み合わせられなかった
npm で配るパッケージを作る tsc のあと node node_modules 配下の .ts は型ストリップの対象外
本番で動かす tsc のあと node、または node で直接実行 実行時に必要な道具が少ない

どの方法でも、型チェックは npx tsc --noEmit で別に行うと考えておくと迷いません(ts-node だけは実行時にも行います)。

コピペできるpackage.jsonのscripts

nodeで直接実行する構成(追加の道具は typescript だけ)

{
  "type": "module",
  "scripts": {
    "start": "node src/main.ts",
    "dev": "node --watch src/main.ts",
    "typecheck": "tsc --noEmit"
  },
  "devDependencies": {
    "@types/node": "^22.20.5",
    "typescript": "^7.0.2"
  }
}
npm run start
npm run dev
main: 1 備品の発注
Completed running 'src/main.ts'. Waiting for file changes before restarting...

node --watch は、ファイルを保存するたびに実行し直します。tsconfig.json は「nodeで直接実行するときのtsconfig.json」の内容を使います。

tsxで実行する構成

{
  "type": "module",
  "scripts": {
    "start": "tsx src/main.ts",
    "dev": "tsx watch src/main.ts",
    "typecheck": "tsc --noEmit"
  },
  "devDependencies": {
    "@types/node": "^22.20.5",
    "tsx": "^4.23.15",
    "typescript": "^7.0.2"
  }
}

tscでビルドしてから実行する構成

{
  "type": "module",
  "scripts": {
    "build": "tsc",
    "start": "node dist/main.js",
    "typecheck": "tsc --noEmit"
  },
  "devDependencies": {
    "@types/node": "^22.20.5",
    "typescript": "^7.0.2"
  }
}

3つの構成の start と、node --watch、tsx watch は、確認環境で main.ts を実行できることを確かめています。

よくある質問

Q. tsxとts-nodeの違いは何ですか? A. いちばんの違いは型チェックです。tsx は型を見ずに変換して実行し、ts-node は実行前に型チェックをして、エラーがあれば止まります。今回の確認では、tsx は paths や拡張子なしの import も解決し、TypeScript 7.0.2 と同じフォルダで動きました。ts-node 10.9.2 は TypeScript の API を使うため、6 系との組み合わせで動きました。

Q. node で直接実行できるなら、tsc はいらなくなりますか? A. 型チェックのために引き続き使います。Node.js は型の注釈を取り除くだけで、型が合っているかは調べません。typeerror.ts が typeerror: 3 と表示されて最後まで動いたのが、その例です。npx tsc --noEmit を scripts の typecheck に登録しておくと安心です。

Q. import の拡張子は .ts と .js のどちらを書けばよいですか? A. node で直接実行するなら .ts です(.js や拡張子なしは ERR_MODULE_NOT_FOUND)。tsc で出力して動かす場合は、.js と書くか、.ts と書いて rewriteRelativeImportExtensions で .js に書き換えてもらいます。後者なら、直接実行と tsc のあと node の両方で同じソースが動きました。

Q. enumを使っているコードをnodeで直接動かすには? A. 3つの道があります。as const のオブジェクトに書き換える(フラグなしで動く)、--experimental-transform-types を付ける(実験的機能の警告が出る)、tsx を使う、のいずれかです。新しく書くコードなら、erasableSyntaxOnly を有効にして最初から書き換え後の形で書くと、どの方法でも動きます。

まとめ

  • Node.js 22.22.2 と 24.21.0 は、node ファイル名.ts だけで TypeScript を実行できる(型ストリップ)。型チェックはしない
  • 型ストリップで動かないのは enum・namespace・パラメータプロパティ・.tsx・パスエイリアス・拡張子なし import。エラーは ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX や ERR_MODULE_NOT_FOUND
  • erasableSyntaxOnly を有効にすると、tsc が TS1294 で事前に知らせてくれる。enum は as const、パラメータプロパティはフィールド宣言に書き換える
  • import は .ts を付け、型には type を付ける。verbatimModuleSyntax を有効にすると TS1484 で気づける
  • tsx は10個のファイルがすべて動いた。paths と JSX を使うコードに向く。型チェックは tsc --noEmit と組み合わせる
  • ts-node は実行時に型エラーで止まる。TypeScript 7.0.2 とは組み合わせられず、6 系と使う
  • 配布するパッケージや本番用は tsc のあと node。paths は出力で書き換わらないので相対パスで書く

参考・出典

  • Node.js 公式ドキュメント「Modules: TypeScript」(v24.x 系の原稿):https://github.com/nodejs/node/blob/v24.x/doc/api/typescript.md
  • Node.js 公式「Running TypeScript Natively」:https://nodejs.org/en/learn/typescript/run-natively
  • Announcing TypeScript 7.0(Microsoft TypeScript 公式ブログ):https://devblogs.microsoft.com/typescript/announcing-typescript-7-0/

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「TypeScriptをNode.jsで実行|tsx・ts-node・型ストリップ」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?