初心者が学ぶ TypeScript 入門 Ver.2.0

# 前回のあらすじ

[TypeScript入門 Ver.0.2](https://qiita.com/ikkitang/items/5ee36fe5786893be5eee)

[TypeScript入門 Ver.0.5](https://qiita.com/ikkitang/items/a5b7fe752dd70eb15fc5)

[TypeScript入門 Ver.1.0](https://qiita.com/ikkitang/items/9acaf6a166f771e5ce6f)

実際にTypeScriptデコーディングしてみて、JSとの違いとか仕様的なのを弄りながら勉強してみた。

今日はモジュールインポートとかエクスポートとかやってみながら学習してみようかと思います。

# httpモジュールをインポートして HTTPサーバーを立てる

httpサーバーを立てるためには httpモジュールを使用する必要がある。 TypeScriptでは、 **import文**を使用する。 例としては以下のような感じです。

```typescript
import * as http from 'http';
```

この構文の意味は、 httpモジュールで export されている変数や関数などをすべて `http` という変数にまとめて `import`する、みたいな意味みたいです。

では、実際にコーディング。

```typescript:app.ts
import * as http from 'http';

// classを指定してクラス化
class MyClass {
    message: String = 'TypeScript';

    // コンストラクター
    constructor() {
        // httpサーバーの設定
        const server: http.Server = http.createServer (
            (request: http.IncomingMessage, response: http.ServerResponse) => 
                this.requestHandler(request, response));
        
        // サーバーを起動してリクエスト待機状態とする.
        server.listen('5001');
    }

    private requestHandler(request: http.IncomingMessage, response: http.ServerResponse) : void {
        response.end('Hello World & ' + this.message + ' for HTTP');
    }
}
   
// MyClassクラスのインスタンスを作る
const myclass = new MyClass();
```

こちらでコンパイルを行う。

そうすると、こんな感じで`app.js`が生成される。

```javascript:app.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const http = require("http");
// classを指定してクラス化
class MyClass {
    // コンストラクター
    constructor() {
        this.message = 'TypeScript';
        // httpサーバーの設定
        const server = http.createServer((request, response) => this.requestHandler(request, response));
        // サーバーを起動してリクエスト待機状態とする.
        server.listen('5001');
    }
    requestHandler(request, response) {
        response.end('Hello World & ' + this.message + ' for HTTP');
    }
}
// MyClassクラスのインスタンスを作る
const myclass = new MyClass();
//# sourceMappingURL=app.js.map
```

`node src/app.js` をおこなって、httpサーバーを立てる事で 今回の例だと 5001ポートで サーバーが　listen（待機） 状態になる。

`http://localhost:5001/` にアクセスする事で、以下のようにレスポンスを得る事が可能。

<div style="border: 1px solid #000000"><img src="https://qiita-image-store.s3.amazonaws.com/0/66498/51bda718-60fc-1a5b-bb90-eb1a5dc89544.png" ></img></div>

これで httpサーバーを立てる事ができた。

## （ちょっと寄り道） 型アノテーションについて

ここでプログラムの記述を変えて試してみる。

### function `: void` の省略

```typescript:app.ts
〜〜
private requestHandler(request: http.IncomingMessage, response: http.ServerResponse) : **void** {
    response.end('Hello World & ' + this.message + ' for HTTP');
}
〜〜
```

この **void**の部分だけど、これを省略するとどうなるんだろう？と疑問になった。 実際に省略してビルドを行ってみたがビルドが実は通る。

で、そうなってくると、ビルドが通るのに、**書く意味あるのか？** に行き着クかと思う。

・・結論いえば、意味はあるんですよね。 これもちゃんとコンパイル時にエラーにしてくれる事があるのです。

例として、以下の２つの関数を考えます。
**戻り値が無い事** が想定されているのに、バグで `return 10;`を返しちゃいました。

このファイルをビルドすると `sample2.ts`は、 定義以外の number型の値が返っているため**ビルドが失敗します**が、なんと、`sample1.ts` は **ビルドは通ります**

```typescript:sample1.ts
// 想定として **return void**
private sample1() {
  return 10;
}
```

```typescript:sample2.ts
// 想定として **return void**
private sample2() : void {
  return 10;
}
```

`: void` は返り値が `void`である事をチェックしてくれます。
バグ等で return をしてしまった時等のために積極的に想定を型として書いてく事を心がけるべきだと思います。

# 外部モジュールを作ってみる。

さて、次は外部モジュールについてです。
よりプログラムの見通しをよくするために機能ごとにファイルを切り分けるのはよくされる事です。 今回はそのようにモジュールを自作で定義して必要なファイルを別に切り分けてみたいと思います。

作りとして、先程の `MyClass`の内容を別モジュールに切り分ける事を考えてみます。 モジュールは `ServerModule.ts`を作成してコーディングしていきます。

```typescript:ServerModule.ts
import * as http from 'http';
 
export class ServerFunction {
  public initServer(): void {
    const server = http.createServer(
        (request: http.IncomingMessage, response: http.ServerResponse) =>
            this.requestHandler(request, response));
    server.listen('5001');
  }
 
  /*
   * サーバーにリクエストがあった時に実行される関数
   */
  private requestHandler(request: http.IncomingMessage,
                         response: http.ServerResponse): void {
    response.end('Hello ServerFunction Class');
  }
}
```

外部ファイルとして想定する場合は `class`の前に **export**キーワードを付けて定義します。

```typescript:app.ts
import {ServerFunction} from './ServerModule';

// classを指定してクラス化
class MyClass {
    // コンストラクター
    constructor() {
        // exportしてきたServerFunctionクラスのインスタンスを作成.
        const serverFunction = new ServerFunction();
        // 関数を実行する。
        serverFunction.initServer();
    }
}
   
// Myclassクラスのインスタンスを作る
const myclass = new MyClass();
```

これで `import {ServerFunction} from './ServerModule';` により `ServerFunction`クラス **のみ**をインポートして使う準備をして適切にインスタンス化して役立てる事ができました。

無事、以下のように表示させる事ができます。

![スクリーンショット 2018-06-08 0.39.20.png](https://qiita-image-store.s3.amazonaws.com/0/66498/823b9edf-c33e-6996-ff16-6c95b9efee2e.png)

# まとめ

取り敢えず、ざっと書いてみた。これぐらいでTypeScriptはOKかな？

型全部書いていくの面倒くさいなー、って思う箇所も確かにあるけど、ぶっちゃけそれ面倒くさがるようだとTypeScript使わない方がいいのでh...ｹﾞﾌﾝｹﾞﾌﾝ

型アノテーションを書くことのメリットとして ちゃんとコンパイル時に想定外を検出くれますので、積極的に書いてバグとおさらばしたいですね。

明日以降の話なんですが、有識者の方からフィードバックを頂いているので `Flowtype`って奴をやってみたいんだな。って気持ちです。 それをやって一回 TypeScriptとかのシリーズは終了しようかなーと思ってます。

# 宣伝

転職をきっかけにいろいろな試みをやってます。

## ほぼ日AWS

[ほぼ日AWS](https://ikkitang1211.hatenablog.jp/archive/category/%E3%81%BB%E3%81%BC%E6%97%A5AWS)

AWSの各ソリューションについて 「このソリューションはどういうもの？」 って観点でまとめてみたものです。

## もくもく独書 for Swift実践入門

[もくもく独書 for Swift実践入門](https://ikkitang1211.hatenablog.jp/archive/category/Swift%E5%AE%9F%E8%B7%B5%E5%85%A5%E9%96%80)

Swift実践入門の書籍を毎日読みながら必要に応じてコードを書いてまとめていっているものです。