TypeScript のサポート

最終更新日: 2017年6月26日

TS と Webpack 2ユーザに向けた、2.2における重要な変更のお知らせ

Vue 2.2 からは 配布ファイルを ES モジュール形式でエクスポートするようにしました。これは webpack 2 が標準で使用する形式です。残念ながら、この変更は意図しないところで破壊的変更をもたらしてしまいました。なぜなら TypeScript と webpack 2 を組み合わせた時、 import Vue = require('vue') は Vue そのものではなく総合的な ES モジュールのオブジェクトを返すからです。

将来的には全ての公式で提供する型宣言を、ES モジュール形式でエクスポートするようにしようと考えています。将来性を考えた推奨構成 を以下に示しているのでご覧ください。

NPM パッケージ内の公式型宣言

静的型システムは、特にアプリケーションが成長するに伴い、多くの潜在的なランタイムエラーを防止するのに役立ちます。そのため、Vue は TypeScript 向けに公式型宣言を提供しており、Vue コアだけでなく Vue RouterVuex も同様に提供しています。

これらは NPM に公開されており、そして最新の TypeScript は NPM パッケージ内の型宣言を解決する方法を知っています。つまり、NPM でインストールした時、TypeScript を Vue と共に使うための追加のツールを必要としません。

推奨構成

// tsconfig.json
{
"compilerOptions": {
// ... 他のオプションは除外しています
"allowSyntheticDefaultImports": true,
"lib": [
"dom",
"es5",
"es2015.promise"
]
}
}

allowSyntheticDefaultImports オプションにより以下の記述が可能となることに留意してください:

import Vue from 'vue'

これは以下の記述の代わりとなるものです:

import Vue = require('vue')

推奨しているのは前者(ES モジュール構文)です。なぜなら推奨している素のES モジュールのやり方と変わらず、そして将来的に全ての公式で提供する型宣言を ES モジュール形式とするように移行しようと考えているからです。

加えて、もし webpack 2 と共に TypeScript を使用しているならば、以下の設定も推奨します:

{
"compilerOptions": {
// ... 他のオプションは除外しています
"module": "es2015",
"moduleResolution": "node"
}
}

このようにすることで TypeScript に対して ES モジュールの import 文をそのまま残すように伝えることができ、そうすると、webpack 2 は ES モジュール をベースとした tree-shaking を利用できます。

より詳細なことについては TypeScript compiler options docs を見てください。

Vue の型宣言の利用

Vue の型定義はたくさんの便利な型宣言をエクスポートしています。例えば、以下は (.vue ファイルにおいて) エクスポートされたコンポーネントオプションオブジェクトにアノテートします:

import Vue, { ComponentOptions } from 'vue'
export default {
props: ['message'],
template: '<span>{{ message }}</span>'
} as ComponentOptions<Vue>

クラススタイルの Vue コンポーネント

Vue のコンポーネントオプションは容易に型でアノテートできます:

import Vue, { ComponentOptions } from 'vue'
// コンポーネントの型を宣言
interface MyComponent extends Vue {
message: string
onClick (): void
}
export default {
template: '<button @click="onClick">Click!</button>',
data: function () {
return {
message: 'Hello!'
}
},
methods: {
onClick: function () {
// TypeScriptは `this` が MyComponent 型で、
// `this.message` が文字列であることを知っています
window.alert(this.message)
}
}
// エクスポートされたオプションオブジェクトに
// MyComponent 型を明示的にアノテートする必要があります
} as ComponentOptions<MyComponent>

残念ながら、ここではいくつかの制限があります:

幸いにも、vue-class-componentは、これらの問題を両方解決できます。これは公式ライブラリで、@Component デコレータでコンポーネントをネイティブな JavaScript クラスとして宣言することができます。例として、上記のコンポーネントを書き直してみましょう:

import Vue from 'vue'
import Component from 'vue-class-component'
// @Component デコレータはクラスが Vue コンポーネントであることを示します
@Component({
// ここではすべてのコンポーネントオプションが許可されています
template: '<button @click="onClick">Click!</button>'
})
export default class MyComponent extends Vue {
// 初期データはインスタンスプロパティとして宣言できます
message: string = 'Hello!'
// コンポーネントメソッドはインスタンスメソッドとして宣言できます
onClick (): void {
window.alert(this.message)
}
}

この構文では、コンポーネントの定義が短くなるだけでなく、明示的なインタフェース宣言がなくても messageonClick の型を推論することができます。この戦略では、算出プロパティ、ライフサイクルフック、描画関数の型を扱うこともできます。詳細な使用方法については、vue-class-component のドキュメントを参照してください。