Vue.jsでTypeScriptを使う方法!【propsでの型定義6つ】

Vue.js Vue.js

今回はVue.jsで公式サポートされたTypeScriptを使ってみます。
はじめにVue CLIでTypeScriptのサポートしているプロジェクトを作成します。

その後にプロジェクトに対して、コンポーネントを追加して、TypeScriptを使用して型定義をしてみています。
公式サイトにはこの辺りに書いています。

この記事に書いているサンプルコードは、下記のバージョンで検証しています。

Vue.js 3.2.13
Vue CLI 5.0.1
TypeScript 4.5.5

Vue.jsでTypeScriptを使う設定のプロジェクトを作成する

Vue CLIを使用して、プロジェクトを作成していきます。
下記のようにコマンドを実行して、test-typescriptの名前でプロジェクトを作成しました。

$ vue create test-typescript

プロジェクト作成時に「Manually select features」を選択して、手動で追加する機能を選びます。

Vue CLI v5.0.1
? Please pick a preset: 
  Default ([Vue 3] babel, eslint) 
  Default ([Vue 2] babel, eslint) 
❯ Manually select features

今回はTypeScriptを使いたいので、下記のようにスペースを押して、TypeScriptにチェックを入れます。

Vue CLI v5.0.1
? Please pick a preset: Manually select features
? Check the features needed for your project: (Press <space> to select, <a> to toggle all, <i> to invert selection, and <enter> to proceed)
 ◉ Babel
❯◉ TypeScript
 ◯ Progressive Web App (PWA) Support
 ◯ Router
 ◯ Vuex
 ◯ CSS Pre-processors
 ◉ Linter / Formatter
 ◯ Unit Testing
 ◯ E2E Testing

チェックした後にエンターを押して進むと、いろいろな設定内容について聞かれるので、今回は下記のように設定しました。

Vue CLI v5.0.1
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, TS, Linter
? Choose a version of Vue.js that you want to start the project with 3.x
? Use class-style component syntax? No
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? Yes
? Pick a linter / formatter config: Basic
? Pick additional lint features: Lint on save
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? No

プロジェクト作成後に、作成したプロジェクトを立ち上げると、下記のようにWelcome画面が表示されます。
「Vue.js + TypeScript」と書いてあって、TypeScriptが追加されていることが確認できます。

Vue.jsでTypeScriptを追加した場合のWelcome画面

Vue.jsでTypeScriptを使用して、コンポーネントを書いてみる

TypeScriptを使用してコンポーネントを書いてみます。
コンポーネントのpropsに型を定義してみました。

<template>
  <div class="border rounded border-blue-300 p-3 m-3 w-5/12">
    {{ name }}さんは{{ age }}歳で、{{ address }}に住んでいます。
  </div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
  props: {
    name: {
      type: String
    },
    age: {
      type: Number
    },
    address: {
      type: String
    },
  }
})
</script>

解説

名前(name)・年齢(age)・住所(address)のデータを渡して、表示するだけのコンポーネントです。

スクリプトの箇所では、下記のようにTypeScript(lang="ts")を設定しています。
このように設定することで、TypeScriptで書いていることをエディタ(VSCode)に認識させることができるようです。

<script lang="ts">

この後にdefineComponentをimportして使用しています。
defineComponentを使用することで、コンポーネントの中で、型推論が効くようになるようです。

そのためTypeScriptで書く場合には、この形式で書くことになります。(まだ試していませんが、ここのリンク先のようにsetupを書いて省略することもできるようです。)

このコンポーネントでは、propsとして下記のようにプロパティを用意しました。

props: {
  name: {
    type: String
  },
  age: {
    type: Number
  },
  address: {
    type: String
  },
}

propsの配下のプロパティが、親のコンポーネントから渡すプロパティ名になります。
そのプロパティにオブジェクトを設定して、typeプロパティに渡す型を書きます。

コンポーネントに対して、違う型を渡すとどうなるのか?

今回はVSCodeを使用して、コードを書きました。
作成したコンポーネントを使う側から、間違ったデータを渡すと、下記のように赤線が引かれて教えてくれます。

Vue.jsのTypeScriptで型を間違える

※VSCodeには拡張機能として、Volarを導入しています。
Volarを導入することによって、上記のようにエラー表示等を行ってくれます。
Veturを既に導入している場合には、Veturは無効にしておく必要があるようです。

公式ドキュメントの下記の箇所に記載がありました。
Using Vue with TypeScript – IDE Support

動作を確認する

動作を確認するために、作成したコンポーネントをApp.vueから下記のように呼び出してみました。
作成したコンポーネントをcomponentsに追加して、呼び出しています。

<template>
  <user-information
    name="taro"
    :age="22"
    address="福岡県博多区"
  />
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import UserInformation from '@/components/UserInformation.vue';

export default defineComponent({
  name: 'App',
  components: {
    UserInformation
  }
});
</script>

そうすると、下記のように渡された値が表示されることが確認できました。

Vue.jsのTypeScriptコンポーネントの動作確認

propsにデフォルトの引数を作成したい

コンポーネントのpropsで値が渡されてない場合のデフォルト引数を定義することが可能です。
typeプロパティと一緒にdefaultプロパティを用意して、デフォルト値を書いておきます。

export default defineComponent({
  props: {
    name: {
      type: String,
      default: 'テスト',
    },
    age: {
      type: Number,
      default: 20,
    },
    address: {
      type: String,
      default: 'テスト住所',
    },
  }
})

上記のように定義したときに、何も値を渡さずに下記のようにコンポーネントを増やしてみました。

<template>
  <user-information
    name="taro"
    :age="22"
    address="福岡県博多区"
  />
  <user-information />
</template>

そうすると、このように値が渡されていないコンポーネントにはデフォルト引数が渡されて表示されます。
Vue.jsのデフォルト引数を確認

propsに必須の引数を設定したい

必須の引数を設定する場合は、typeプロパティと一緒にrequiredを設定します。

props: {
  name: {
    type: String,
    required: true,
  },
}

そうすると、引数が設定されていない場合は、下記のようにエラーメッセージが表示されます。

Vue.jsで必須引数を確認

propsで渡せる型定義のまとめ

文字列

文字列はStringで定義します。

props: {
  text: {
    type: String,
  },
},

渡すときは、下記のような形になります。

<type-test text="テスト" />

数値

数値はNumberで定義します。

props: {
  number: {
    type: Number,
  },
},

渡すときは、下記のような形になります。

<type-test :number="777" />

論理値

論理値はBooleanで定義します。

props: {
  bool: {
    type: Boolean,
  },
},

渡すときは、下記のような形になります。

<type-test :bool="true" />

配列

配列はArrayで定義します。

props: {
  testArray: {
    type: Array,
  },
},

渡すときは、下記のような形になります。

<type-test :test-array="['test1', 123, 'test2']" />

上記では、いろいろな型のデータが渡せるようになっています。
配列の型まで指定するには、下記のようにPropTypeを使用して、propsに定義しておきます。

import { defineComponent, PropType } from 'vue';

export default defineComponent({
  props: {
    testArray: {
      type: Array as PropType<Array<string>>,
    },
  },
});

こうしておくと、配列の値は文字列のみを許可して、数値などが渡された場合はVSCode上でエラーになります。

関数

関数を渡すときはFunctionで定義します。

props: {
  testFunction: {
    type: Function,
  },
},

渡すときは、下記のような形になります。
setupメソッドでalertHello関数を作成して、渡しています。
こうしておくと、コンポーネントの中で、親から渡した関数を使用することが可能です。

<template>
  <type-test :test-function="alertHello" />
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import TypeTest from './components/TypeTest.vue';

export default defineComponent({
  name: 'App',
  components: {
    TypeTest
  },
  setup () {
    const alertHello = () => {
      alert("hello")
    }

    return {
      alertHello,
    }
  }
});
</script>

定義した型オブジェクト

型定義を作成して、propsに渡す場合にもPropTypeを使用します。

まず、型を作成しておきます。
今回はLikeFoodという名前の型を作成しました。
名前と色と価格をプロパティとして持っています。

export type LikeFood = {
  name: string;
  color: string;
  price: number;
}

この型をコンポーネントのpropsで受け取る場合は、下記のようにPropTypeを使用して、作成した型を記載します。

props: {
  myFood: {
    type: Object as PropType<LikeFood>
  }
},

こうすることで、この型以外が指定された場合にVSCode上でエラーになります。

Vue.jsで定義した型を渡さなかった場合のエラー表示

コメント

タイトルとURLをコピーしました