2018/5 TypeScriptを1年使い込んでみた感想

以前、 2017/6 TypeScriptを使ってみたを紹介しました。

あれから約1年、TypeScriptで1万行コーディングしたでのフィードバックです。

印象

型の安心感は絶大

関数引数の型指定やajaxで取得したデータの型定義をしておくと、 仕様変更や機能拡張したときに影響範囲や考慮漏れが一目瞭然。自信を持って改修ができます。

習熟すればJSと同じスピードで使える

最初の2週間ぐらいは、記法や設計に四苦八苦しました。学習コストは0ではないです。 しかし、習熟した後はJSと同じ感じでサクサク実装できました。

TypeScriptいい!

慣れた今の印象としては、総じてTypeScriptはいいものだと思っています。

使い所

じゃあJavaScriptを置き換えるものなのか?というと、そうは思いません。以下のような場合に、TypeScriptを使うことを検討すると良いでしょう。

こういった場合に型が役立つと感じました。結局の所、型は複雑なシステムにおいて人間をサポートしてくれるツールということでしょうか。逆に1000行以下だとJSで十分だと思います。

環境構築

せっかくなので今時点での入門用に簡単なTypeScript環境構築手順を紹介します。

Node準備

TypeScriptはNode.jsを利用しているので、まずはNode準備をしましょう。

Node.jsインストール

Node.jsからインストーラーをダウンロードしてインストールする。

# バージョン確認
> node -v

プロジェクト作成

Node.jsのパッケージ管理ファイルを作成します。

# 任意のフォルダを作って移動
> mkdir myapp
> cd myapp

# 初期化(適当にyesやenter押下でOK)
> npm init

インストール

# wepbackとTypeScriptをインストール
> npm install --save-dev webpack webpack-cli typescript ts-loader

設定

ちょっとややこしいですが、以下3つの設定ファイルを設定します。

webpack設定ファイル

TypeScriptをJSファイルに変換するためにwebpackを使います。 任意のフォルダ配下にwebpack設定ファイルwebpack.config.jsを作成。(myapp/webpack.config.js)

module.exports = (env, argv)=>{

    return {
        // エントリーポイント
        entry: './src/app.ts',
        // JSファイル名(本番JSに上書きしないように別名に)
        output:{
            filename: (argv.mode == 'production') ? '[name].js' : '[name]_dev.js'
        },
        // ソースマップ出力
        devtool: (argv.mode == 'production') ? false : 'inline-source-map',
        // import対象拡張子
        resolve:{
            extensions: ['.ts']
        },
        module:{
            rules:[
                {
                    // 対象拡張子
                    test: /\.ts$/,
                    // コンパイラ
                    use: 'ts-loader'
                }
            ]
        }
    };
}

TypeScript設定ファイル

任意のフォルダ配下にTypeScript設定ファイルtsconfig.jsonを作成。(myapp/tsconfig.json) 色々オプション指定できるのですが、入門としてはこれで十分だと思います。

{
    "compilerOptions":{
        "sourceMap": true,
        "target": "es5",
        "module": "es2015",
        "typeRoots": ["./node_modules/@types"]
    }
}

Node設定ファイル

作成されたpackage.jsonにビルドコマンドをscriptsにdevとproを登録します。

{
  "name": "ts",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "dependencies": {},
  "devDependencies": {
    "ts-loader": "^4.2.0",
    "typescript": "^2.8.1",
    "webpack": "^4.5.0",
    "webpack-cli": "^2.0.14"
  },
  "scripts": {
    "dev": "webpack --progress --colors --watch --mode development",
    "pro": "webpack --progress --colors --mode production"
  },
  "author": "",
  "license": "ISC"
}

proコマンドはproductionモードでビルドされminifyされたJSができあがります。 devコマンドはdevelopmentモードでビルドされデバッグしやすいJSとソースマップができあがります。 devコマンドには--watchオプションをつけておりコマンドは終了しません。ソースコードを編集し上書きすると、自動で再ビルドしてくれます。ctrl+cで終了してください。

ライブラリ

TypeScriptはひと手間必要になります。@typesでライブラリの型情報もインストールしましょう。 今回はnodeとjQuery。

> npm install --save-dev @types/node @types/jquery

こういった準備をしてライブラリも型支援を受けられます。 この@typesはMicrosoftのBOTが自動で型情報を収集したもののようです。

実装

好きな実装を行っていきます。今回はapp.tsとButton.tsを作ってみます。

app.ts

src/app.tsを作成。Buttonをインポート、生成、bodyに追加してみました。

import {Button} from './Button';

$(document).ready(()=>{
    const button = new Button();
    $('body').append(button.el());
});

Button.ts

src/Button.tsを作成。ボタンクラスを作成しました。privateやpublic、引数に型とTypeScriptらしい内容にしました。

export class Button {

    private element:JQuery;

    constructor(){
        this.element = $('<button>ボタン</button>');

        this.element.on('click', this.onClick.bind(this));
    }

    public el():JQuery{
        return this.element;
    }

    private onClick(event:JQueryEventObject):void{

        if(process.env.NODE_ENV == 'production'){
            console.log('click! 本番です.');
        }else{
            console.log('click!');
        }
    }
}

ビルド

開発者用ビルド

> npm run dev

src/app.tsからビルドされたJSがdist/main_dev.jsに出力されます。

本番用ビルド

> npm run pro

src/app.tsからビルドされたJSがdist/main.jsに出力されます。

備考