Vue.jsのプロジェクトでTypeScriptを使いたい

# はじめに

ここ最近、TypeScriptが注目を浴びているように思います。TypeScriptはJavaScriptの世界に「型」を導入し、またES6以降の文法をES5以下の文法で表現できるように変換してくれる有り難い存在です。しかしながらVue.jsのプロジェクトでTypeScriptを使うのはこれまで難しいことでありました。なぜなら、View ModelのコンストラクタがTypeScriptのクラス構文と相性が悪かったからです。

```typescript:app.ts
class App {
    firstname: string;
    lastname: string;
    
    constructor(firstname: string, lastname: string) {
        this.firstname = firstname;
        this.lastname = lastname;
    }
    
    get fullname(): string {
        return `${this.firstname} ${this.lastname}`;
    }
    
    set fullname(fullname: string) {
        const [firstname, lastname] = fullname.split(" ");
        this.firstname = firstname;
        this.lastname = lastname;
    }
    
    greet() {
      console.log(`My name is ${this.fullname}.`);
    }
}
```

他のフレームワークないしライブラリならこのように書いて`this`の型をはっきりさせることができます。Angular 2やReact、AureliaなどはTypeScriptを使うときクラス構文を使用するのが普通ですし、Backbone.jsやKnockoutJSでもTypeScriptを利用することは容易いことです。一方でVue.jsは以下のようにコンポーネントを定義します。この書き方はとてもわかりやすくて良いのですが、これをTypeScriptで書いたとしても`this`の型が何であるか、TypeScriptにとってはわからず、型の恩恵を受けることができません。

```javascript:app.js
const App = Vue.extend({
  data: () => ({
    firstname: "",
    lastname: ""
  }),
  computed: {
    fullname: {
      get() { return `${this.firstname} ${this.lastname}` }
      set() {
        const [firstname, lastname] = fullname.split(" ");
        // thisがなんだかわからない
        this.firstname = firstname;
        this.lastname = lastname;
      }
    }
  },
  methods: {
    greet() {
      console.log(`My name is ${this.fullname}.`);
    }
  }
})
```


# 目的
1. Vue.jsのコンストラクタにTypeScriptのクラス構文を利用して`this`の型をはっきりとさせる。
2. Vue.jsとTypeScriptを使って何かしらのアプリケーションを作成し、その有用性を確認する。

# 方法
## はじめに
今回採用する方法はTypeScriptデコレータを使う方法です。Angular 2やAureliaで見慣れている人が多いと思います。`Vue`コンストラクタを継承して`_init`メソッドを呼び出す方法もありますが、それと比較して

* プライベートなメソッドを呼び出さずに済む
* 関心の分離ができる

といったメリットがあります。その一方デコレータを多用するためコンパイル後のコード量が増加します。
それから、ファイルのコンパイルにWebpackとts-loader、それからhtml-loaderを利用します。

## ダウンロードするもの

### Dependencies
* Vue.js
* vue-class-component

### Dev Dependencies
* TypeScript
* Webpack
* ts-loader
* html-loader


## 作るもの
今日は12月4日、『新世紀エヴァンゲリオン』に登場するキャラクター「惣流・アスカ・ラングレー」の誕生日であります。したがって彼女の誕生日をお祝いするアプリケーションを作ろうと思います。
また、『ご注文はうさぎですか？』のチノちゃんも12月4日が誕生日だそうです。

### 型定義ファイルを用意する
DefinitelyTypedから必要な型定義ファイルをダウンロードしたり、自分で書いたりします。
`vue.d.ts`を割と最新のものに更新し、`vue-router.d.ts`をDefinitelyTypedに登録しました。ぜひお使いください。さらに`vue-resource.d.ts`もDefinitelyTypedに登録しました。


# 結果
[ここ](https://github.com/kaorun343/vue-typescript-example)に公開しました。
最近書き換えました。ダウンロードしてブラウザで`public/index.html`を開いてみてください。
せっかくなのでBootstrap 4を使ってみました。

# 考察
よくできたと思います。APIの変更などが多いので大変です。でもこれからも更新頑張ります。

# 終わりに
## 次のバージョンについて
過去のバージョン名は以下のとおりです。

* Blade Runner
* Cowboy Bebop
* Dragon Ball
* Evangelion
 
アルファベット順になっていることがわかります。したがって次期バージョンはおそらく『蒼穹のファフナー（Fafner in the Azure）』か『すべてがFになる（Subete ga F ni Naru）』が適当だと思っています。

# 参考にしたサイト・ページ
* [vue.js](http://vuejs.org)
* [vuejs/vue](https://github.com/vuejs/vue/)
* [vuejs/vue-class-component](https://github.com/vuejs/vue-class-component/)
* [Typescript and Vue in general · Issue #478 · vuejs/vue](https://github.com/vuejs/vue/issues/478)
* [Welcome to TypeScript](http://www.typescriptlang.org)
* [TypeScriptのDecoratorメモ - Qiita](http://qiita.com/Quramy/items/e3a43bb1734b8a7331e8)
* [TypeScriptの型定義ファイルを共有しよう！ - Qiita](http://qiita.com/vvakame/items/1980d4b6cc222e03fdcb)