sequelizeを利用したコードのtypescript化

# 背景

今回は、前回書いたsequelizeのコードのtypescript化を試してみます。
https://qiita.com/yusuke-ka/items/448843020c0406363ba5#sequelize%E3%81%A7%E5%AE%9F%E8%A3%85

上記で作成したプロジェクト「sequelize」を直接変更してtypescriptのコードにしてみようと思います。

# typescriptへの変更


typescriptおよびexpressの型とts-node(typescriptのコードを直接実行できる)をインストール。

```
> yarn add -D typescript @types/node @types/express ts-node
```

package.jsonにscriptを追加してtsc(typescript)とts-nodeが簡単に実行できるようにしておく。

```package.json
...
"scripts": {
  "sequelize": "sequelize",
  "tsc": "tsc",
  "dev": "ts-node index.ts"
},
...
```

次にsequelizeの公式に書いてあるtypescript化時に必要な依存をインストールしておく。
https://sequelize.org/v5/manual/typescript.html

```
> yarn add -D @types/validator @types/bluebird 
```


とりあえず、tsconfig.jsonを生成。

```
yarn tsc --init
```

前回作ったindex.jsをindex.tsにリネームして少しだけ書き換え。

```index.ts
import express from "express";
const app = express();
const db = require("./models/index");

app.get("/", function (req: express.Request, res: express.Response) {
  res.send("Hello World!");
});

app.post("/create", function (req: express.Request, res: express.Response) {
  db.TestClass.create({
    attr1: "test",
  }).then(() => {
    res.send("Data Created.");
  });
});

app.listen(3000, () => console.log("Example app listening on port 3000!"));
```

書き換えたのは、expressのrequireをimportに変えたのと、app.getやapp.post内のfunctionの引数reqとresに型を付けただけ。

実行してみる。

```
> yarn dev
```

「Advanced REST client」で動作確認。
http://localhost:3000/create にPOSTリクエストを送ってみる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643184/11761f24-87eb-ad4f-8358-791f90a580f1.png)

成功したけど、typescriptの恩恵を受けられている気がしないので、もう少し頑張ってみる。

公式のTypeScript関連のページを見ながら、型定義ファイルを作ってみた。
　https://sequelize.org/master/manual/typescript.html#usage-of--code-sequelize-define--code-

```index.d.ts
import { Model, BuildOptions, DataTypes } from "sequelize";

interface TestClassModel extends Model {
  readonly id: number;
  attr1: string;
  readonly createdAt: date;
  readonly updatedAt: date;
}

type TestClassModelStatic = typeof Model & {
  new (values?: object, options?: BuildOptions): TestClassModel;
};

const TestClass = <TestClassModelStatic>sequelize.define("TestClass", {
  id: {
    primaryKey: true,
    type: DataTypes.INTEGER.UNSIGNED,
  },
  attr1: {
    type: DataTypes.STRING,
  },
  createdAt: {
    type: DataTypes.DATE,
  },
  updatedAt: {
    type: DataTypes.DATE,
  },
});
```

これをindex.jsがあるmodelsフォルダに置いてみる。

現状、フォルダ構成はこうなっている。

```
|- sequelize
  |- node_modules/
  |- config/
    |- config.json
  |- migrations/
    |- {yyyymmddhhmmss}-create-test-class.js
  |- models/
    |- index.js
    |- index.d.ts
    |- testclass.js
  |- seeders/
  |- index.ts
  |- package.json
  |- tsconfig.json
  |- yarn.lock
```

呼び出し元のindex.ts(プロジェクト直下のやつ)を少しだけ変更。

(変更前)

```index.ts
import express from "express";
const app = express();
const db = require("./models/index");
...
```

(変更後)

```index.ts
import express from "express";
const app = express();
import db from "./models/index";
...
```

※dbをimportに変えた。

こうすることで、呼び出し元で補完が効くようになった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643184/8f235f7a-64c2-7540-a7e6-89539cf862a8.png)

# さいごに

sequelizeを使って書いたコードをtypescriptに変更してみた。

現状、modelの呼び出し元はtypescriptっぽく書くことは出来そうだけど、model側もtypescript化できたらいいなと思う。

時間がなくて今回は中途半端になってしまったので、次はmodelファイルをtypescript化できないか試してみようと思う。