年末休みにnodeでAPIサーバを勉強した復習〜part3 Typescript化の説明

一応、うちのプログラマへの教育を兼ねてメモを残している
Part3は前回の開発への補足 Typescriptについて

#Typescript
基本的にnodeではEcmascriptの新しい文法が使えるが
静的型付を行ったり、便利なのでTypescriptを採用した

##tsconfig
tsconfig.js にて設定を行う

```json:tsconfig
    "target": "ES2018",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
    "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
    "outDir": "./dist",                        /* Redirect output structure to the directory. */
    "rootDir": "./src",                       /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
    "strict": true,                           /* Enable all strict type-checking options. */
```

見ての通りで ES2018の文法を使う
nodeなのでcommonjsを使う
ソースのディレクトリとトランスパイルの出力ディレクトリを設定する

strictは型の厳密チェックだ
現在はこれのみONにしているが、慣れてきたら1つずつエラーを厳しくしていく予定だ
下記のエラーチェックがある

```
 "strict": true,                           /* すべての厳密な型チェックオプションを有効にします。 */
    // "noImplicitAny": true,                 /* 暗黙の 'any'型で式と宣言のエラーを発生させます。 */
    // "strictNullChecks": true,              /* 厳密なヌルチェックを有効にします。 */
    // "strictFunctionTypes": true,           /* 関数型の厳密なチェックを有効にします。 */
    // "strictPropertyInitialization": true,  /* クラスのプロパティ初期化の厳密なチェックを有効にします。 */
    // "noImplicitThis": true,                /* 暗黙の 'any'型で 'this'式のエラーを発生させます。 */
    // "alwaysStrict": true,                  /* 厳密なモードで解析し,各ソースファイルに対して "use strict"を発行します。 */
    /* 追加チェック */
    // "noUnusedLocals": true,                /* 未使用のローカルのエラーを報告します。 */
    // "noUnusedParameters": true,            /* 未使用のパラメータのエラーを報告します。 */
    // "noImplicitReturns": true,             /* 関数内のすべてのコードパスが値を返さない場合,エラーを報告します。 */
    // "noFallthroughCasesInSwitch": true,    /* switchステートメントのfallthrough caseのエラーを報告します。 */
 ```

##型をつける
https://qiita.com/Rock22/items/d7ae96464bdbf297c6ec
Typescriptは Number,string,boolean,any,配列などの型があり
型がない変数はエラーになるので全てに型をつける必要がある

```typescript
let n: number;
n = 1;
```

のように型を指定する
型がわからないものは、コンパイル通すためにanyでもしてあとで直す

##types
npmでインストールしたモジュールはjavascriptで書かれてる
型情報がなくてもTypescriptで実行する事は出来るが
型をつけると、コード補完がきくし、型を間違えるとコンパイル時にエラーが発生する
ので、モジュールに対して型情報を作る必要があるが
大抵のライブラリは有志が型情報ファイルを作ってくれている
例えば expressの型情報は

```bash
npm install --save @types/express
```

のようにすれば良い。


##import
JavaScriptのモジュールはかなり厄介
元々のJavaScriptではそれらの概念が欠乏していて
BrouserifyやらWebpackでJavaScriptを1ファイルにまとめたり苦労していた
他にもRequire.jsやCommon.jsを使いモジュール化を行っていた
node.jsではCommon.jsのモジュールシステムが使われる
ES6ではimportが追加されたが、それと同じものがTypescriptには備わっている

common.jsのRequireとimportの違いは下記のようになっている

https://qiita.com/rooooomania/items/4c999d93ae745e9d8657

importにはdefaultが設定できる。それも下記で
https://qiita.com/bmf_san/items/bdb67c7abf4d381cf976

大雑把にいえば
exportsオブジェクトとdefaultオブジェクトあり、importによりそれらのオブジェクトに値が入る



```typescript
-var express = require('express');
+import express from 'express';

-const app = require('./config/express');
+import app from './config/express';

-const express = require('express');
+import express, { Response, Request } from "express";
あるいは
+import { default as express, Response, Request } from "express";

-const userRoutes = require('./user.route');
+import userRoutes from './user.route';

```

こんな風に変更する
一言でいえば importで {}なしだとdefault、{}はそれ以外のものをimportする
asで名前を変更できる

export側も変更する

```typescript
-async function status_insert(req) {
+export async function status_insert(req: Request) {

-module.exports = router;
+export default router;
```

関数や変数を export修飾するとimport可能になる( {}でくくる )
export default default xxx はdefaultとしてexportする（ ｛｝不要 ）
当然defaultは1つしか書けない

他にもモジュール化にはいろいろ文法あるので、読んでおいて。