JavaScript
Node.js
TypeScript

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

前回のあらすじ

TypeScript入門 Ver.0.2

TypeScript入門 Ver.0.5

TypeScript入門 Ver.1.0

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

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

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

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

import * as http from 'http';

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

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

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が生成される。

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/ にアクセスする事で、以下のようにレスポンスを得る事が可能。

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

(ちょっと寄り道) 型アノテーションについて

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

function : void の省略

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

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

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

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

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

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

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

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

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

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

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

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キーワードを付けて定義します。

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

まとめ

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

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

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

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

宣伝

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

ほぼ日AWS

ほぼ日AWS

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

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

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

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