Madogiwa Blog

主に技術系の学習メモに使っていきます。

Vue.jsでVue.extendを使ってTypeScriptで書くときのMEMO

Vue.jsをTypeScriptで書くときには、vue-class-componentvue-propaty-decoratorを使うような情報ふが多いですが、Vue.extendを使うとそれらを使わないピュアなVue.jsでもTypeScriptを使って書くことが出来ます。

jp.vuejs.org

そのへんの書き方とかを、あまり理解出来てなかったのでMEMOしておきます✍

基本的な書き方

下記にvue-class-componentのOverviewにあったカウンターをちょっと改変してVue.extendを使って書き直したものを記載しました

class-component.vuejs.org

vue-class-componentだと素のVue.jsのコンポーネントとかなり書き方が違ってしまうのですが、

<template>
  <div>
    <button @click="decrement(1)">-</button>
    {{ count }}
    <button @click="increment(1)">+</button>
  </div>
</template>
<script lang="ts">
import Vue from 'vue'

interface Data {
  count: number
}

export default Vue.extend({
  props: {
    initCount: Number
  },
  data() : Data {
    return {
      count: this.initCount | 0
    }
  },
  methods: {
    decrement(num: number) {
      this.count -= num;
    },
    increment(num: number) {
      this.count += num
    }
  }
})
</script>

ちょっとDataの型指定が癖がある感じがしますが素のVue.jsのコンポーネントライクで書けるので読みやすいですね👍

Propsを独自で定義したObjectで受け取るケースは下記のような形になるようです👀
※下記は受け取ったコメントのオブジェクトをそのまま表示するようなコンポーネントです

<template>
  <div class="comment" style="border: solid; margin: 5px;">
    <p class="attribute">{{comment.id}}</p>
    <p class="attribute">{{comment.body}}</p>
  </div>
</template>
<script lang="ts">
import Vue, { PropType } from 'vue'
import { Comment } from '../types/types'

export default Vue.extend({
  props: {
    comment: Object as PropType<Comment>
  }
})
</script>

PropTypeはVue.jsのAPIです。 https://github.com/vuejs/vue/issues/6850

Vue.jsのpropsは内部的にはObjectそのものではなくObjectのコンストラクタが渡されており、 TypeScriptの型情報はObjectのコンストラクタの実行時には存在しないのでエラーになってしまうようです。(あまりわかってない)

frontendsociety.com

そのため今までは関数として定義していたようですが、それがわかりにくいということでPropTypeが追加された経緯のようです。

<template>
  <div class="comment" style="border: solid; margin: 5px;">
    <p class="attribute">{{comment.id}}</p>
    <p class="attribute">{{comment.body}}</p>
  </div>
</template>
<script lang="ts">
import Vue, { PropType } from 'vue'
import { Comment } from '../types/types'

export default Vue.extend({
  props: {
    comment: Object as (() => Comment)
  }
})
</script>

参考

qiita.com

count0.org