TypeScript, Node.js, Express を一緒に使う方法



設定ファイル（package.json）作成
npm init -y で作成

---
TypeScriptの設定ファイル（tsconfig.json）作成
tsc --init で作成

---
nodemonインストール
nodemonとは、ソースコードの変更を監視し、自動的にnodeコマンドを再起動してくれるnpmパッケージです。

npm install --save-dev nodemon

---
Expressインストール
Node.js のための高速で、革新的な、最小限のWebフレームワーク

$ npm install express --save


---
requireを理解させる（@types/nodeをインストール）
npm install -save-dev @types/node　でインストール


---
expressの型定義ファイル（@types/express）をインストール
npm install --save-dev @types/express でインストール。

#Node.jsのモジュール

```practice-import.js
const practice = require('./practice-export');
console.log(practice);
```

```practice-exports.js
module.exports = {
  hello 'hello'
}
```

↓出力結果
[![Image from Gyazo](https://i.gyazo.com/133991351d040bc5f99c58f20028620d.png)](https://gyazo.com/133991351d040bc5f99c58f20028620d)
requireすると、const practiceがmodule.exportsのオブジェクトになります。

↓関数でも成り立ちます。

```practice-import.js
const practice = require('./practice-export');
console.log(practice());
```

```practice-exports.js
module.exports = function() {
  return 'hello'
}
```

[![Image from Gyazo](https://i.gyazo.com/27493b7a539d0f6e846f67b83aac53c4.png)](https://gyazo.com/27493b7a539d0f6e846f67b83aac53c4)

また、Node.jsでは、予め↓が内部的に実行されています。

```practice-exports.js
module.exports = {}
exports = module.exports;
```

↑exportsは１行目の{ }を参照しています。

#TypeScriptsのモジュールとNode.jsのモジュールの相互関係

```practice-exports.ts
export default 'hello'
```

```practice-import.ts
import practice from './practice-export';
console.log(practice)
```

↓Node.jsの書き方にコンパイル

```practice-exports.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = 'hello';
```

```practice-import.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const practice_export_1 = require("./practice-export");
console.log(practice_export_1.default);
```

import　→ require
それを使うときは、.defaultとしています。

↓例えばaxios.jsの最後の行には、このように書かれています。

```axios.js
// Allow use of default import syntax in TypeScript
module.exports.default = axios;
```

これは、TypeScriptの書き方でもOKとしてくれているのです。

####外部のパッケージなどを使う場合のimportの書き方

↓Node.jsのrequire文を使いたい場合は、TypeScriptは２つの選択肢を用意しています。

```ts
import * as express from 'express';
import express = require('express');
```

#esModuleInteropを使ってNode.jsのモジュールにデフォルトimportを使用する方法
TypeScriptで書いたファイルも、他の外部から来たファイルも、
どちらにも対応するシステムです。

```practice-import.ts
import practice from './practice-export';
console.log(practice)
```

↓TypeScriptで書いた場合、基本的に__esModuleが、exportされるものに付きます。
↓＿esModuleが付かないのは、export = を使ったときです。

```practice-import.js
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const practice_export_1 = __importDefault(require("./practice-export"));
console.log(practice_export_1.default);
```

Object.definePropertyによって、
「exportsというオブジェクトに、__esModuleというメンバーを加える。そのプロパティの値はtrueですよ。」
というのが、自動的にTypeScriptからトランスパイルされたJavaScriptのファイルに付きます。

####import * as の場合

```practice-import.ts
import * as practice from './practice-export';
```

↓イメージは、オブジェクトA,B,Cがあった場合、A,B,C,defaultというように、４つ目に付く
↓defaultというメンバーの中に、またA,B,Cというオブジェクトが付く感じで出力されます。

```practice-import.js
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const practice = __importStar(require("./practice-export"));
console.log(practice);
```

####allowSyntheticDefaultImports
esModuleInteropと非常に似たものですが、あくまで「型チェック」のみに使われます。
「BabelやWebpackにやってもらいたいけど、TypeScriptの型のチェックはデフォルトimportで通したい」といったときに使います。

allowSyntheticDefaultImportsがフロント寄り。
esModuleInteroがNode.js寄り。

#Expressを使ってルーティングの処理をする

↓localhost:3000にアクセスすると、Helloと表示されます。

```ts
import express from 'express';
const app = express();
app.get('/', (req, res, next) => {
  res.send('<h1>Hello</h1>')
})
app.listen(3000);
```

↓上から順番に実行されるものをミドルウェアと言います。nextを付けないと実行されません。

```ts
import express from 'express';
const app = express();
app.use('/', (req, res, next) => {
  next();
})
app.use('/', (req, res, next) => {
  next();
})
app.use('/', (req, res, next) => {
  next();
})
app.get('/', (req, res, next) => {
  res.send('<h1>Hello</h1>')
})
app.listen(3000);
```

useの' / 'は、/ から始まるものは全て適用されます。

####エラーハンドリング
↓エラーハンドリングです。
↓どこかでエラーが見つかれば、Expressが認識して、
↓この関数にエラーが集まって、関数内の処理が実行されます。

```ts
app.use((err, req, res, next) => {
  next();
})
```

VSCode
ctrl + ーで一つ前に戻れる。