【2020年6月版】VSCodeでTypeScript + Nodeプロジェクトをデバッグする

## TL;DR
[devinoue/typescript-node-project](https://github.com/devinoue/typescript-node-project)
こちらからご使用ください。

## インストール
### よく使うパッケージのインストール

基本的なパッケージを入れます。

```shell
yarn add -D ts-node ts-node-dev typescript @types/node
```

以下のような内容になっています。

| パッケージ名 | 役目                                                         |
| ------------ | ------------------------------------------------------------ |
| ts-node      | tscを使ってプリコンパイルなしにTypeScriptを実行するnpmパッケージ。<br />typescriptコンパイラはバンドルされていないので、別にインストールする必要あり。 |
| ts-node-dev  | ts-nodeでwatchをするために必要                               |
| typescript   | TypeScriptコンパイラ                                         |
| @types/node  | Nodeのデフォルトモジュールの型定義。                         |

### tsconfig.json

TypeScriptのConfigファイルを作ります。この辺りは定型文ですね

```shell
npx tsc --init

# tscがグローバルインストールされている場合
tsc --init
```

とはいえ、さすがに毎回tsconfig.jsonを設定しなおすのは面倒なので、僕は以下のようなものを使いまわしています。
(pathsプロパティを使って、ルートディレクトリからの絶対パスや相対パスの代わりに~ or @を使えるようにしています)

```json:tsconfig.json
{
  "compilerOptions": {
    "target": "es2018",
    "module": "commonjs",
    "moduleResolution": "node",
    "lib": [
      "es6",
      "dom"
    ],
    "esModuleInterop": true,
    "rootDir": "./src",
    "outDir": "./out",
    "sourceMap": true,
    "strict": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "baseUrl": ".",
    "paths": {
      "~/*": [
        "./src/*"
      ],
      "@/*": [
        "./src/*"
      ]
    },
    "types": [
      "@types/node"
    ]
  },
  "exclude": [
    "node_modules",
    "dist",
    "**/*.spec.ts"
  ],
  "include": [
    "src/**/*"
  ]
}
```

## ESlint & Prettier

```shell
# ESlint
yarn add -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin

#Prettier
yarn add -D prettier eslint-config-prettier eslint-plugin-prettier

```



eslintの設定ファイル(自分の場合)

```javascript:.eslintrc.js

module.exports = {
  env: {
    browser: true,
    es6: true,
    node: true,
  },
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:prettier/recommended',
    'prettier/@typescript-eslint',
  ],
  globals: {
    Atomics: 'readonly',
    SharedArrayBuffer: 'readonly',
  },
  parser: '@typescript-eslint/parser',
  parserOptions: {
    sourceType: 'module',
  },
  plugins: ['@typescript-eslint'],
  rules: {
    'prettier/prettier': [
      2,
      {
        singleQuote: true,
        semi: false,
        arrowParens: 'always',
        parser: 'typescript',
      },
    ],

    '@typescript-eslint/explicit-function-return-type': 'off',
    '@typescript-eslint/explicit-module-boundary-types': 'off',
  },
}

```

### package.jsonのscripts

```json:package.json
  "scripts": {
    "dev": "ts-node src/index.ts",
    "dev:w": "ts-node-dev --respawn ./src/index.ts",
    "build": "tsc",
    "start": "node out/index.js",
    "lint": "eslint --ext .js,.ts --ignore-path .gitignore ."
  },
```

`yarn dev:w`で実行したまま作業したりできます。



## VSCodeでのデバッグ関連

VSCode上でデバッグできるよう、以下のファイルを追加しておきます。

```
root
└ .vscode
　 ├ launch.json
　 └ tasks.json
```

```json:tasks.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Launch TypeScript",
      "program": "${file}",
      "preLaunchTask": "Compile TypeScript",
      "cwd": "${workspaceFolder}",
      "console": "integratedTerminal",
      "outFiles": [
        "${workspaceFolder}/out/**/*.js"
      ]
    }
  ]
}
```

このコンパイルをするのが以下のtasks.jsonになります

```json:tasks.json
{
    // tasks.json 形式の詳細についての資料は、
    // https://go.microsoft.com/fwlink/?LinkId=733558 をご覧ください
    "version": "2.0.0",
    "tasks": [
        {
            "label": "Compile TypeScript",
            "type": "typescript",
            "tsconfig": "tsconfig.json",
            "problemMatcher": [
                "$tsc"
            ]
        }
    ]
}
```

これでコードにブレークポイントを置き、VSCodeの左ペイン「実行」から「Launch TypeScript」をクリックしてデバッグができるはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294146/7ae8dc7e-c7fb-8882-b3ea-d629d9aa4ea4.png)

## Jestを入れる
追記2020/06/10

JestとTypeScript関連のモジュールを入れる。

```shell
yarn add jest @types/jest ts-jest -D
```

プロジェクトルートのディレクトリに`jest.config.js`を作り以下の内容を埋める。

```javascript
module.exports = {
  "roots": [
    "<rootDir>/src"
  ],
  "testMatch": [
    "**/__tests__/**/*.+(ts|tsx|js)",
    "**/?(*.)+(spec|test).+(ts|tsx|js)"
  ],
  "transform": {
    "^.+\\.(ts|tsx)$": "ts-jest"
  },
}
```

※Jestでは「すべてのTypeScriptファイルをプロジェクトのsrcフォルダに入れることを常にお勧めします」とのことで、僕もそうしています。

あとは`tsconfig.json`に以下を追加する

```json:tsconfig.json
{
  "compilerOptions": {
    "types": [
        "jest"
      ]
  },
}
```


## 参考

[VSCodeでESLint+typescript-eslint+Prettierを導入する v3.0.0](https://qiita.com/madono/items/a134e904e891c5cb1d20)

[TypeScript + Node.js プロジェクトのはじめかた2019](https://qiita.com/notakaos/items/3bbd2293e2ff286d9f49)