2020-07-13
ts-nodeで静的型を利用したスクリプト処理を実行する

ts-nodeを使えば、その名のとおりあたかもTypeScriptをnode.jsのようにそのまま実行できるようになります。これによって静的型チェックの恩恵をうけたり、既存の型定義やTypeScript資産を有効利用したスクリプト処理を、逐一コンパイルするよりもずっと気軽に開発・利用できます。

インストール

ts-nodeはnode.jsとTypeScriptが利用できる環境で実行される必要があるので、これらの実行環境が整っていない場合は先にそちらをインストールしてください。

自分の開発マシンではnode.js同様に任意の場所ですぐ実行できるようにグローバルインストールして問題ないと思います。

npm install -g ts-node

またプロジェクトごとにインストールする場合は、TypeScriptもプロジェクトごとにインストールします。

npm install --save-dev typescript ts-node

基本的な使い方

ファイルの実行

node.jsと同様に以下のように対象ファイルを指定して実行します。

ts-node 実行ファイル名

グローバルインストールせずにプロジェクトごとにインストールした場合、例えば、プロジェクトのルートで実行する場合は以下のようにnode_modules以下のバイナリを実行します。

./node_modules/.bin/ts-node 実行ファイル名

(例)

以下のように関数に型付けしたhello.tsを実行する時、node hello.tsではSyntaxErrorを起こしてしまいます。

function say_hello(name: string): void {
    console.log("Hello, " + name + "!")
}

say_hello("ts-node")

ts-nodeを利用すればそのまま実行することができます。

$ ts-node hello.ts 
Hello, ts-node!

対話型

ファイル名を指定しなければ、node.js同様、対話型で実行するもできます。ただ、対話型で実行する場合はTypeScriptの大きなメリットである静的型チェックを利用できません。挙動を簡単に確認したい場合などを除いて、実際に作業する場合などはnode.jsを利用するほうが速さなどを考慮して優れている場合ばかりだと思います。

ts-node

コンパイラオプションをいじる

実際に僕が体験したts-nodeの利用ケースとして、「TypeScriptで書かれた製品をビルドするときに、中間ファイルの生成などの前処理をTypeScriptで書きたい」という場面がありました。前処理と製品の間で型定義を共有できるのでメリットは大きいのですが、一方、例えば製品側ではesnextのモジュールを利用したいのに前処理はcommonjsで書きたいなど、別のコンパイル設定を利用したいことがあります。

ts-nodeでは実行場所にtsconfig.jsonがあればそれを参照してTypeScriptのコンパイルを行っているので、特に何もしなければ製品とコンパイラオプションを分けることができません。コンパイラオプションの上書きは以下のように対応するJSONを与えることで可能です。

ts-node -O コンパイラオプションのJSON 実行ファイル
# または
ts-node --compiler-options コンパイラオプションのJSON 実行ファイル

(例) ./node_modules/.bin/ts-node -O '{ "module": "commonjs" }' 実行ファイル

また、通常のtscコマンド同様、--projectオプションで参照する設定ファイルを指定することもできるので、例えばscript.tsconfig.jsonといった名前で設定を保存しておいて

ts-node --project script.tsconfig.json 実行ファイル

といった具合に別に設定を保存・利用することもできます。