トップ画像
VSCodeのVueでpropsの型チェックをする方法 (TypeScript)

執筆者: sasigume

最終更新: 10/26/2021

注意書き


以下の内容は

  • VSCode 1.16.2
  • Vetur v0.35.0
  • Nuxt v3.0.0-27252999.d2cc9e4 (Vue: 3.2.20)
  • Next 11.1.2 (React: 17.0.2)

時点の内容です。あと、当然ですが全てTypeScriptです。
Nuxt3はまだベータ版ですが、起動が早い + TypeScriptが使いやすいので皆さんも試してみてください。

Vueでpropsの型チェックをさせる方法

ステップ1. Veturを入れる

https://github.com/vuejs/vetur

これがないと話にならないです。

ステップ2. 設定を変える

なぜかデフォルトで型チェックできないので、settings.json に以下の設定を追記します。

{
  (前略)
  "vetur.validation.templateProps": true,
  "vetur.experimental.templateInterpolationService": true,
  (後略)
}


ステップ3. コンポーネントを作成する

<template>
  <div>
    <h2>{{ name }}様</h2>
    <div v-if="age">
      <b>{{ age }}歳なので</b>
      <span>わいの{{ age && age / 20 }}倍!</span>
    </div>
  </div>
</template>


<script lang="ts">
export default {
  name: "TestComponent",
  props: {
    name: {
      type: String,
      required: true,
    },
    age: {
      type: Number,
      required: false,
    },
  },
}
</script>


name は文字列(必須)で、年齢は数値(任意)です。

「名前と年齢を受け取って、年齢があれば俺の年齢と比較する」という意味不明なコンポーネントです。

ステップ4. ページで使ってみる

<template>
  <div>
    <TestComponent name="aaa" :age="100" />
  </div>
</template>

<script lang="ts">
import TestComponent from "../components/TestComponent.vue"

export default {
  components: { TestComponent },
}
</script>


こんな感じでページで使います。


できましたね。

ステップ5. エラーを起こしてみる

<TestComponent name="aaa" age="100" />


試しにこう書いてみてください。


Type 'string' is not assignable to type 'number'.


Veturから怒られるはずです。なぜならage="100" が文字列の「100」を渡しているからです。

が、templateInterpolationService がまだ「experimantal」なので、エラーが出る場所がおかしいです。

ちょっと待って!Reactで書けばいいやん

あのですね、なんで単なる自動補完に、拡張機能と設定がわざわざ必要なんですか?

Reactで同じことをやってみてください。何も設定がいらないです。

ステップ1. コンポーネントを書く

interface Props {
  name: string;
  age?: number;
}

const TestComponent: React.VFC<Props> = (props) => (
  <div>
    <h2>{props.name}様</h2>
    {props.age && (
      <div>
        <b>{props.age}歳なので</b>
        <span>わいの{props.age / 20}倍!</span>
      </div>
    )}
  </div>
);
export default TestComponent;


めっちゃ短くなります。

型の定義も、ただTypeScriptのinterfaceを書けばいいのです。Vueのprops よりスッキリしていて見やすいでしょう?

Next.jsのページで使う

import TestComponent from '@/components/TestComponent';
import { NextPage } from 'next';

const TestPage: NextPage = () => (
  <div>
    <TestComponent name="aaa" age={100} />
  </div>
);

export default TestPage;



もしage に数値以外を渡すと、その場でエラーが出ます。繰り返しますが、拡張機能や設定は必要ありません。

Vueはpropsだけで記述量が多すぎる

そもそもですね、たかが「名前と年齢を出す」だけで記述量が多すぎるんですよ。

export default {
  name: "TestComponent",
  props: {
    name: {
      type: String,
      required: true,
    },
    age: {
      type: Number,
      required: false,
    },
  },
}


これ、「nameとageを受け取る」ってだけですよ。長すぎるでしょ。

interface Props {
  name: string;
  age?: number;
}

const TestComponent: React.VFC<Props> = (props) => (
  <div>
    <h2>{props.name}様</h2>
    {props.age && (
      <div>
        <b>{props.age}歳なので</b>
        <span>わいの{props.age / 20}倍!</span>
      </div>
    )}
  </div>
);
export default TestComponent;


さっきも書きましたけど、Reactはテンプレート自体を含めてこの長さですからね。絶対こっちの方が時間の節約になります。

以上、俺がReactを使う理由の記事でした。

---

あれ?なんの記事だったっけ?

思い出した!自動補完や!

以上、VSCodeのVueでpropsの型チェックをさせる方法でした。

取得に失敗しました

2021年度 入部

Twitter GitHub YouTube