TypeScirptでnode.js(express)を動かす

July 24, 2019

ts-nodeを使ってTypeScriptでexpressを動かす環境を構築しました。

インストール

今回は簡単にts-nodeを使って動かします。

GitHub - TypeStrong/ts-node: TypeScript execution and REPL for node.js

npm i express
npm i -D @types/express ts-node typescript

起動ファイル

./src/index.tsをこのような感じにします。

import express from "express";ではエラーが出てしまったので*をつける形で対処しています。

import * as express from "express";
const app = express();
const port = 3000;

app.get("/", (req, res) => res.send("Hello World!"));

app.listen(port, () => console.log(`Example app listening on port ${port}!`));

tsconfig.json

tsconfig.jsonはこんな感じにしました。

{
  "compilerOptions": {
    "outDir": "./dist",
    "sourceMap": true,
    "module": "esnext",
    "target": "es5",
    "moduleResolution": "node",
    "removeComments": true,
    "strictNullChecks": true,
    "allowSyntheticDefaultImports": true
  },
  "include": ["./src/**/*"],
  "exclude": ["./node_modules"]
}

モジュールインポートでエラー

ts-nodeで起動してみるとエラーが出ました。モジュールのインポートのところでコケています。

express-docker-practice/src/index.ts:1
(function (exports, require, module, __filename, __dirname) { import * as express from "express";
                                                              ^^^^^^

SyntaxError: Unexpected token import
    at createScript (vm.js:80:10)
    at Object.runInThisContext (vm.js:139:10)
    at Module._compile (module.js:617:28)
    at Module.m._compile (/express-docker-practice/node_modules/ts-node/src/index.ts:473:23)
    at Module._extensions..js (module.js:664:10)
    at Object.require.extensions.(anonymous function) [as .ts] (/express-docker-practice/node_modules/ts-node/src/index.ts:476:12)
    at Module.load (module.js:566:32)
    at tryModuleLoad (module.js:506:12)
    at Function.Module._load (module.js:498:3)
    at Function.Module.runMain (module.js:694:10)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! express-docker-practice@1.0.0 dev: `ts-node ./src/index.ts`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the express-docker-practice@1.0.0 dev script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/satoshi/.npm/_logs/2019-07-23T23_00_52_020Z-debug.log

"module": "commonjs",を指定するとうまく行きました。

TypeScriptで"SyntaxError: Unexpected token import"になったときの解決方法 - zuckey blog

最終的なtsconfig.jsonです。

{
  "compilerOptions": {
    "outDir": "./dist",
    "sourceMap": true,
    "module": "commonjs",
    "target": "es5",
    "moduleResolution": "node",
    "removeComments": true,
    "strictNullChecks": true,
    "allowSyntheticDefaultImports": true
  },
  "include": ["./src/**/*"],
  "exclude": ["./node_modules"]
}

実行

./node_modules/.bin/ts-node ./src/index.tsで実行できます。localhost:3000にアクセスしてHello worldと表示されれば成功です。

$ ./node_modules/.bin/ts-node ./src/index.ts 
Example app listening on port 3000!

import文でのエラー

index.tsで、import express from "express";では下記エラーが出てしまいました。importするときの形式の問題だと思いますが、解決できなかったので*をつける形でimport * as express from "express";として対処しました。

/express-docker-practice/src/index.ts:2
const app = express();
                   ^
TypeError: express_1.default is not a function
    at Object.<anonymous> (/express-docker-practice/src/index.ts:2:20)
    at Module._compile (module.js:653:30)
    at Module.m._compile (/express-docker-practice/node_modules/ts-node/src/index.ts:473:23)
    at Module._extensions..js (module.js:664:10)
    at Object.require.extensions.(anonymous function) [as .ts] (/express-docker-practice/node_modules/ts-node/src/index.ts:476:12)
    at Module.load (module.js:566:32)
    at tryModuleLoad (module.js:506:12)
    at Function.Module._load (module.js:498:3)
    at Function.Module.runMain (module.js:694:10)
    at Object.<anonymous> (/express-docker-practice/node_modules/ts-node/src/bin.ts:158:12)

ソースコード

ここまでのソースコードはこちらに置いてあります。

sandbox/express-docker-practice at 01e151cf2ce2cbfd6e6077e21661617e38ed3b1e · SatoshiKawabata/sandbox · GitHub

参考

TypeScriptでExpress.js開発するときにやることまとめ (docker/lint/format/tsのまま実行/autoreload) - Qiita