TypeScriptの勉強し始めたのでひとまず開発環境を構築してみた

# はじめに

JavaScriptでのフルスタック技術を学んできたので、学びを発展させようと思ってTypeScriptに手を出してみました。

TypeScriptはあくまでAltJavaScriptであって、最終的にはJavaScriptに変換することを前提にした言語です。
記事執筆時点ではNodeJSは直接にはTypeScriptをサポートしていないので、TypeScriptの設定なしにNodeJS等ではデバッグ等を実行することができません。
なのでTypeScriptで開発するためには色々と設定を追加する必要があります。


# 使用するパッケージ

[NodeJS](https://nodejs.org/en/)
[npm](https://www.npmjs.com)
[TypeSCript](https://www.typescriptlang.org)


# 実行環境

MacbookPro Mid 2014
macOS Catalina ver.10.15.6
VSCode for Mac ver.



## 1.TypeScript言語環境インストール

TypeScript環境をインストールします。TypeScriptはaltJavaScript、つまりJavaScriptの拡張系として提供されているのでJavaScriptの開発環境を発展させる形で導入していきます。
TypeScript環境は`npm`パッケージの形でインストール提供されているので、以下のコマンドでインストールします。

```
$ npm install -g typescript
$ tsc -v
Version 4.0.2
```

バージョン確認ができればインストール完了です。私の環境では`sudo`が必要でした。

上記コマンドではグローバルにインストールしていますが、プロジェクト単位で開発用ライブラリとしてインストールすることもできます。

```
//By npm
$ npm install typescript --save-dev
$ npx tcs -v
Version 4.0.2

//By yarn
$ yarn add typescript --dev
$ npx tcs -v
Version 4.0.2
```

これでローカルでのインストール完了です。ですが、`tsc`コマンド単独では動作しなくなっています。
[npx](https://www.npmjs.com/package/npx)を利用しないと`tsc`コマンドが動作しません。

Qiita等の日本語で記述された記事ではローカルにインストール、一方で[TypeScript](https://www.typescriptlang.org/)のチュートリアル等(特に英語資料)ではグローバルインストールをするように記述してあります。
おそらくnpmパッケージの形とはいえ新たに言語環境をインストールするのですからプロジェクト単位ではなく、OS自体にグローバルで言語サポートを追加する方が適していると考えられたのかと思います。
なのでプロジェクト単位でTSCのバージョンも管理しているなどしているのでなければグローバルでインストールするほうがいいかと思います。


### 2.TypeScript→JavaScriptのトランスパイル設定

TypeScriptパッケージをインストールしたとはいえ、TypeScriptはあくまでaltJavascriptなのでJavaScriptに変換、トランスパイルしないと動作しません。
しかし、JavaScriptは進化の変遷が激しく、ES4以前とES5以降では文法が大きく変わります。
実行環境の違いも含めて、ひと口にJavaScriptと言ってもフォーマットの幅がとてつもなく広くなっています。

`tsconfig.json`ファイルを作成することで、JavaScriptへのトランスパイル設定を記述することができます。
ただし、`tsconfig.json`はプロジェクト単位でしか作成できず、グローバルでの作成、設定の適用はできません。


まずは`tsconfig.json`を作成します。プロジェクトフォルダで`tsc`の初期化を実行します。

```
$ tsc --init
```

これでプロジェクトフォルダ直下に`tsconfig.json`が作成されます。
`tsc`コマンドを使用しなくても作成はできますが、`tsc --init`で作成すると可能な設定項目、オプションがコメントアウトされた状態で作成されるのでコマンドで初期化するほうがいいでしょう。

`tsconfig.json`が作成されたら設定を調整していきます。
React等のライブラリやフレームワークに対応した設定項目まであるので、プロジェクトごとに必要なものだけを有効化、設定するほうがいいでしょう。

ひとまず今回はフレームワーク等を一切使用しない設定にしてみました。

```JavaScript:tsconfig.json
{
  "target": "ES2015",
  "module": "commonjs",
  "sourceMap": true,
  "rootDir": "./src",
  "outDir": "./build",
  "strict": true,
}
```

作成後`tsconfig.json`を手動で編集してもいいですが使用するオプションが決まっているのなら`tsc --init`にをつけることでオプション設定済みの状態で`tsconfig.json`作成できます。

```
$ tsc --init --target ES5 --module commonjs --sourceMap --rootDir ./src --outDir ./build --strict
```


各項目の詳細は以下のとおりです。

  - "target": "ES5"
    + トランスパイル後のJavaScriptの形式。役割としては[babel](https://babeljs.io/)と同じようなもの考えればいいのかな。最近の環境ならES5にしておけばまず困ることはないでしょう
  - "module": "commonjs",
    + モジュールの読み込み方式。特に理由がなければcommonjsにしておけば問題はないみたいです(es系統だとブラウザでしか動かない模様。)
  - "sourceMap": true
    + [ソースマップファイル](https://developer.mozilla.org/ja/docs/Tools/Debugger/How_to/Use_a_source_map)(tsファイルとトランスパイル後のjsファイルを関連付けるファイル)を作成するかどうかのオプション。これがないとtsファイルのデバッグができないので、あえてるす理由がなければ`true`にしておくほうが良い
  - "rootDir": "./src"
    + トランスパイル対象のtsファイルの格納ディレクトリを指定する。言い換えればここで指定したディレクトリ以下のtsファイルしかトランスパイルされない。指定ディレクトリ以外にtsファイルが存在するときにはトランスパイルエラーとなる。ファイルの構造化の観点からもモジュール単体を作成するとき以外は設定しておいたほうが良さそう
  - "outDir": "./build"
    + トランスパイルしたjsファイルの格納ディレクトリ。ディレクトリ構造は維持された状態で格納される。一つのファイルにまとめないのならこれでいいかと
  - "strict": true
    + [use strict](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Strict_mode)を使用するか選択します。使わない理由も特に思いつかないので`true`にしておきます


開発目的や環境に関わらず、新しく開発を行うのであれば最低限これだけは設定してけおけばいいかなと思います。
あとはプロジェクトや使用するフレームワーク/ライブラリ、好みで設定していけばいいと思います。


### 3.デバッグ環境構築

NodeJSデフォルトのままではTypeScriptのサポートしていないので、デバッグするにもトランスパイルとTypeScript用のデバッグ設定をする必要があります。
`tasks.json`を作成してトランスパイル実行のビルドタスクを構成し、`launch.json`を作成してTypeScriptのデバッグ設定を追加していきます。


#### 1-3-1.ビルドタスクの設定

TypeScriptをトランスパイルするタスクを構成します。このタスクをデバッグ中に呼び出すことでデバッグを実行の過程で自動的にトランスパイルが実行されて、TypeScriptのデバッグができるようになります。
VSCodeでプロジェクトフォルダを開いた状態で`command shift B`を押します。すると下の画像のようにビルドタスクを選択するドロップダウンメニューが表示されます。


![build_task.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654516/5004fb8b-2630-b7c0-5942-9270a9a40b6b.png)



`tsc: ビルド -tsconfig.json`の欄の右端にあるアイコンをクリックすると`tasks.json`が作成されるので保存します。
内容はデフォルトのままで大丈夫です。このjsonの中の`label`で指定された名前がこのビルドを呼び出すためのキーとなります。


```JavaScript:tasks.json
{
	"version": "2.0.0",
	"tasks": [
		{
		"type": "typescript",			
		"tsconfig": "tsconfig.json",
		"problemMatcher": ["$tsc"],
		"group": "build",
		"label": "tsc: ビルド - tsconfig.json"
		}
	]
}
```


#### 3-2.デバッグ設定の作成

VSCodeのサイドバーのデバッグアイコンから`launch.jsonの作成`をクリックし、`NodeJS`を選択してNodeJS環境向けの`launch.json`を作成します。
作成された`launch.json`に以下の設定を追加します。

```JavaScript:launch.json
{
  "version": "0.2.0"
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "NodeJS(TypeScript)",
      "cwd": "${workspaceFolder}",
      "preLaunchTask": "tsc: ビルド - tsconfig.json",
      "program": "${file}",
      "skipFiles": ["<node_internals>/**"],
      "outFiles": ["${workspaceFolder}/build/**/*.js"]
    }
  ]
}
```

各項目の詳細は以下の通り。

  - "type": "node"
    + デバッグに使用する実行環境の種類。NodeJS環境で実行するので`node`で
  - "request": "launch"
    + デバッグの実行形式。新たにプログラムを実行してデバッグする`launch`と、起動済のプログラムにデバッグを実行する`attach`の2種類がある。特に理由がなければ`launch`で問題なし
  - "name": "NodeJS(TypeScript)"
    + デバッグ設定の登録名、もちろん任意に変更できる。今回はNodeかつTypeScriptであるとわかるようにしてみた
  - "cwd": "${workspaceFolder}"
    + `current working directory`の略。実行対象のプログラムのルートフォルダを指定する、これを設定しないとモジュールの読み込み等で各PATHが取得できなくなる。`${workspaceFolder}`とすることで、現在開いているワークスペースのルートフォルダを指定できる
  - "preLaunchTask": "tsc: ビルド - tsconfig.json"
    + デバッグ前に実行するタスク。デバッグ実行前にトランスパイルを実行しいないと動作しないので、ここで実行するように指定する。`tasks.json`に記述されたトランスパイル設定の'label'と同じ名前を指定することで`tasks.json`の記述に従ってトランスパイルが実行される
  - "program": "${file}"
    + デバッグで実行する対象プログラム。ファイルを直接指定することもできるが、それだと単独のファイルしかデバッグ対象とならない。`${file}`とすることで現在開いているファイルがデバッグ対象になる
  - "outFiles": ["${workspaceFolder}/build/**/*.js"]
    + 出力されるjsファイルのディレクトリを指定します。これがないとトランスパイル後のjsファイルの所在を認識できないのでここで`tsconfig.json`の`outDir`で設定したディレクトリを指定します


デバッグを実行すると、以下の流れで実行されます。

  1. デバッグ呼び出すと`launch.json`からデバッグ設定を読み込む
  2. `launch.json`から`preLaunchTask`を読み込んで、デバッグの前に実行する
  3. `task.json`から`preLaunchTask`で指定されたタスクを読み込み、そこから対象のtsファイルをビルド(トランスパイル)し、完了後のファイルでデバッグを実行


### 3-3 Node.js実行環境

デバッグ設定はできたので、開発に向けての環境設定を構築していきます。
Nodejsでサーバーを構築すると開発中は`nodemon`を利用してサーバーを常時稼働/自動再起動するのが便利なのでよく利用します。
ですが`nodemon`はJavaScript用なので`ts`ファイルは直接実行できません。
そこで別のNPMパッケージ`ts-node`を利用して`nodemon`で`ts`ファイルが実行できるようにしていきます。

[nodemon](https://www.npmjs.com/package/nodemon)
[ts-node](https://www.npmjs.com/package/ts-node)

`ts-node`は指定したファイルに記述された依存関係も含めてトランスパイルなしに`ts`ファイルを実行します。

依存関係が記述された`ts`ファイルも依存関係読み込んだ上で動作するので。
(`ts-node`はトランスパイル無しで`ts` ファイルを実行してくれますがデバッグではないのでブレークポイントに対応してくれません。デバッグには別途構築する必要があります。)

```
$ yarn add nodemon ts-node
```

```JavaScript:package.json
"scripts": {
    "server": "npm run build:live",
    "build": "tsc -p .",
    "build:live": "nodemon --watch 'src/**/*.ts' --exec 'ts-node' src/index.ts",
    "start": "node ./build/js "
},
```

  - `yarn build`
    + `tsconfig.json`があればその設定に従って.ts ファイルをトランスパイル(ビルド)する
  - `yarn start`
    + `yarn build:live`を実行する
  - `yarn build:live`
    + nodemonが`ts-node`で`src/index.ts`を実行する。`nodemon`は`src/`以下の`ts`ファイルを監視し更新の都度、src/index.tsを再起動する


### 4 React.js実行環境

ReactでもTypeScriptが利用可能です。細かくオプションをカスタマイズして構成することもできますが、`create-react-app`がTypeScriptにも対応しているのでそれを利用して簡単にReactを構成していきます。


```
$ npx create-react-app my-app --template typescript
```

これでカレントディレクトリに`my-app`という名前でTypeScriptに対応したReactアプリケーションが作成されます。
プロジェクトフォルダに移動して、`npm start`または`yarn start`でReactアプリケーションが起動します。


## まとめ

  - `launch.json`で設定した`preLaunchTask`の詳細、つまりビルド(トランスパイル)の設定をする
  - `launch.json`からビルドを実行するには`tasks.json`で設定する必要がある
  - `tasks.json`のグローバル設定が不可、したがってデバッグ設定はどうしてもローカル単位になる
  - Nodejs、Reactjsアプリを構築するときは別途環境設定が必要


# あとがき

結構面倒ですね…。断続的に勉強してきたのもありますがオプションをここまで理解するのに延べ1週間はかかりました。
環境構築をしないとデバッグすらできないと思って先に環境構築周りを調べたのですがオプション事項が多くて調べるのに時間がかかりました。

ともあれようやくこれで開発に着手…できませんね、まだ肝心の型の学習が終わってません苦笑。


# 参考&参照した記事

[TypeScript](https://www.typescriptlang.org/docs/)
[VSCode Debugging](https://code.visualstudio.com/docs/editor/debugging)
[VScode Variable-Reference](https://code.visualstudio.com/docs/editor/variables-reference)
[サバイバルTypeScript](https://book.yyts.org)
[TypeScriptDeepDive日本語](https://typescript-jp.gitbook.io/deep-dive/)