TypeScript を直接実行できる ts-node 便利ですよね。
ところで、最近 (ってほどでもないですが) Node.js 界隈 ESM へ移行する流れがあります。
Node.js 界隈で多くの OSS をリリースしておられる Sindre さんのパッケージも、多くが ESM Native になっており、この流れは止められないでしょう。
ところで、 ESM Native で実行するとなると、 TypeScript で困るのが、拡張子問題です。
TypeScript は基本的に .ts
もしくは .tsx
な拡張子を解決するのを望むわけで、それをコンパイルしても .js
に直してくれるわけではありません。
これの何が困るか、というと、 ts-node
で ESM として実行する場合、 import
分にトランスパイル後の拡張子 .js
を含めたパスを記述する必要があり、直感的ではありません。
ということで、なんとかしましょうというのが、今回の記事。
目標は、以下のようなファイルを ts-node src/index.ts
みたいな感じで直接実行することです。
import { sayHello } from "./hello"; sayHello();
const sayHello = () => console.log("Hello"); export { sayHello };
といっても、やり方は簡単で、コンパイル時に .js
を差し込んでしまえばいいわけです。
ということで、やっていきましょう。
まず、 ts-node
で直接 ESM を実行することは出来ないので、以下のように呼び出します。
$ yarn run ts-node --esm src/index.ts
ただ、これだけだと拡張子が解決されないので、書き換えてもらいましょう。
都合が良いことに、そういうことをしてくれるものがあるので、導入します。
$ yarn add ttypescript typescript-transform-extensions --dev
次に、 tsconfig.json
に以下を追加します。
{ "compilerOptions": { // ... "plugins": [ { "transform": "typescript-transform-extensions", "extensions": {".ts": ".js"} } ] } }
最後に、 ts-node
で ttypescript
を使うように設定を変更します。
$ ts-node --esm --compiler ttypescript ./src/index.ts
これで完成です。
あとは、これを package.json
の scripts
に追加してあげれば、汎用性が上がって良いですね。
{ "name": "example-package", "version": "0.0.0", "type": "module", "scripts": { "ts:esm": "ts-node --esm --compiler ttypescript", "hello": "npm run ts:esm src/index.ts" } }
ということで、新年はじめの記事でした。