本文へジャンプ

TypeScript で Vue を使用する

TypeScript のような型システムは、ビルド時に静的解析で多くの一般的なエラーを検出できます。これにより、本番環境でのランタイムエラーの確率を下げ、より自信を持って大規模アプリケーションのコードをリファクタリングできるようになります。TypeScript は、IDE における型ベースの自動補完により、開発者の人間工学も改善します。

Vue 自体が TypeScript で書かれており、第一級の TypeScript のサポートを提供します。全ての公式 Vue パッケージには型定義が付属されているため、すぐに利用することができます。

プロジェクトのセットアップ

create-vue は公式のプロジェクトセットアップツールで、Vite を用いた TypeScript 対応の Vue プロジェクトをセットアップするためのオプションを提供します。

概要

Vite ベースのセットアップでは、開発サーバーとそのバンドラーはトランスパイルのみ行い、型チェックは行いません。これにより、Vite の開発サーバーは TypeScript を使用していても超高速に動作し続けることが保証されます。

  • 開発中は、すぐに型エラーのフィードバックを得るために、優れた IDE セットアップ に頼ることを推奨します。

  • SFC を使用する場合、コマンドラインでの型チェックと型宣言の生成には vue-tsc を使用します。vue-tsc は TypeScript 独自のコマンドラインインターフェースである tsc のラッパーです。TypeScript のファイルに加えて Vue SFC をサポートする以外は、tsc とほぼ同じように動作します。Vite の開発サーバーと並行して、vue-tsc をウォッチモードで実行するか、別のワーカースレッドでチェックを実行する vite-plugin-checker のような Vite プラグインを使用できます。

  • Vue CLI は TypeScript もサポートしていますが、推奨されなくなりました。以下の注意を参照してください。

IDE のサポート

  • Visual Studio Code(VS Code)は、すぐに利用できる TypeScript サポートを提供しているため、強く推奨されます。

    • Vue - Official(元 Volar)は公式 VS Code 拡張機能です。Vue SFC 内部での TypeScript のサポートなど、その他の優れた機能を持ちます。

      TIP

      Vue - Official は Vue 2 の公式 VS Code 拡張機能である Vetur を置き換えるものです。現在 Vetur がインストールされている場合、Vue 3 のプロジェクトで必ず無効化してください。

  • WebStorm は TypeScript と Vue の両方をすぐに利用できるようサポートしています。他の JetBrains IDE も最初から、または この無料プラグイン で、これらをサポートしています。バージョン 2023.2 では、WebStorm と Vue プラグインは Vue Language Server をビルトインでサポートしています。Settings → Languages & Frameworks → TypeScript → Vue で、すべての TypeScript バージョンで Volar インテグレーションを使用するように Vue サービスを設定できます。デフォルトでは、Volar は TypeScript バージョン 5.0 以上で使用されます。

tsconfig.json の構成

create-vue を使ってセットアップしたプロジェクトには、構成済みの tsconfig.json が含まれます。ベースとなった構成は @vue/tsconfig パッケージにて抽象化されています。プロジェクト内部では、Project References を使って、異なる環境(例: アプリコードとテストコードで異なるグローバル変数を持つ必要がある)で実行されるコードに対して正しい型を保証しています。

tsconfig.json を手動で構成する場合、いくつかの注目すべきオプションは以下の通りです:

参照:

Vue CLI と ts-loader に関する注意

Vue CLI など、webpack ベースのセットアップでは、モジュールの変換パイプラインの一部で、例えば ts-loader を使って型チェックを行うことが一般的です。しかし、これは型チェックを行うためにモジュールグラフ全体の知識が必要となるので、クリーンな解決法とは言えません。個々のモジュールの変換ステップは、単にこのタスクを行うための良い方法ではないのです。これは、以下のような問題を引き起こします:

  • ts-loader は変換後のコードしか型チェックができません。これは、IDE や vue-tsc でみられる、ソースコードに直接マップされるエラーとは一致しません。

  • 型チェックは遅くなる可能性があります。コード変換と同じスレッド / プロセスで行われると、アプリケーション全体のビルド速度に大きく影響します。

  • すでに IDE で型チェックを別のプロセスで実行しているので、開発体験を低下させるコストは、単純に適切なトレードオフではありません。

現在、Vue CLI 経由で Vue 3 + TypeScript を使っている場合、Vite への移行を強く推奨します。トランスパイルのみでの TS サポートを有効にする CLI オプションにも取り組んでいるので、型チェックのために vue-tsc に切り替えることができます。

一般的な使用上の注意

defineComponent()

TypeScript がコンポーネントオプション内の型を適切に推論できるようにするには、defineComponent() を使ってコンポーネントを定義する必要があります:

ts
import { defineComponent } from 'vue'

export default defineComponent({
  // 型推論が有効
  props: {
    name: String,
    msg: { type: String, required: true }
  },
  data() {
    return {
      count: 1
    }
  },
  mounted() {
    this.name // type: string | undefined
    this.msg // type: string
    this.count // type: number
  }
})

<script setup> を使わずに Composition API を使用する場合、defineComponent()setup() に渡された props を推論することができます:

ts
import { defineComponent } from 'vue'

export default defineComponent({
  // 型推論が有効
  props: {
    message: String
  },
  setup(props) {
    props.message // type: string | undefined
  }
})

参照:

TIP

defineComponent() は、プレーンな JavaScript で定義されたコンポーネントに対しても型推論を行うことができます。

単一ファイルコンポーネントでの使用法

SFC で TypeScript を使用する場合、<script> タグに lang="ts" 属性を追加してください。lang="ts" が存在する場合、全てのテンプレート内の式に対してもより厳格な型チェックを利用できます。

vue
<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
  data() {
    return {
      count: 1
    }
  }
})
</script>

<template>
  <!-- 型チェックと自動補完が有効 -->
  {{ count.toFixed(2) }}
</template>

lang="ts" は、<script setup> とともにも使用できます:

vue
<script setup lang="ts">
// TypeScript が有効
import { ref } from 'vue'

const count = ref(1)
</script>

<template>
  <!-- 型チェックと自動補完が有効 -->
  {{ count.toFixed(2) }}
</template>

テンプレート内での TypeScript

<template> は、<script lang="ts"><script setup lang="ts"> が使われている場合、バインディング式について、TypeScript をサポートします。これは、テンプレート内の式で型キャストを行う必要がある場合に便利です。

不自然な例を以下に示します:

vue
<script setup lang="ts">
let x: string | number = 1
</script>

<template>
  <!-- x は string の可能性があるためエラー -->
  {{ x.toFixed(2) }}
</template>

これはインラインの型キャストで回避することができます:

vue
<script setup lang="ts">
let x: string | number = 1
</script>

<template>
  {{ (x as number).toFixed(2) }}
</template>

TIP

Vue CLI または webpack ベースのセットアップを使用する場合、テンプレート内の式での TypeScript の使用には vue-loader@^16.8.0 が必要になります。

TSX の使用方法

Vue では、JSX / TSX を使ったコンポーネントの作成もサポートしています。詳細については、レンダー関数と JSX で説明しています。

ジェネリックコンポーネント

ジェネリックコンポーネントは以下の 2 つのケースでサポートされています:

API 固有のレシピ

TypeScript で Vue を使用するが読み込まれました