LoginSignup
257
182

More than 3 years have passed since last update.

[Vue+TypeScript] Vue.extend で Vue らしさを保ちつつ TypeScript で書くときの型宣言についてまとめた

Last updated at Posted at 2019-07-04

はじめに

Vue + TypeScript の組み合わせでVueを書くときに、vue-property-decorator を利用して書いていくことが多いと思います。
ただ vue-property-decorator を利用すると、どうしてもVueらしさがなくなるというか、よりTypeScriptにらしい書き方になると感じています。
せっかくJavaScriptでVue書けるようになったのに、全然書き方が違うじゃないか…と挫折しかけることもあるんじゃないでしょうか?
ちなみに私は vue-property-decorator で書くほうが慣れているので好きですが、Vue入門者には厳しいところがあると思うので、 Vue.extend ベースでTypeScriptを書いていくという方法を紹介するのと、その際の型宣言についてもまとめていこうと思います。

VueをTypeScriptで書きたいけど、 vue-property-decorator は使いたくない…って人の参考になればいいなーと思います。

Vue.extend ??

TypeScript内でVueモジュールをimport/extendして書く方法です。
JavaScriptでのVueコンポーネントの記述に近い書き方でTypeScriptを書くことができます。

<script lang="ts">
  import Vue from "vue"

  export default Vue.extend({
    name: "component",
    data() {
      return {
        value: "hoge"
      }
    }
  })
</script>

環境構築

VueCLIで簡単に構築することができます。
TypeScriptを選択して、class-styleコンポーネントシンタックスを利用しないと選択すればいいです。

? Check the features needed for your project: (Press <space> to select, <a> to toggle all, <i> to invert selection)
 ◯ Babel
❯◉ TypeScript
 ◯ Progressive Web App (PWA) Support
 ◯ Router
 ◯ Vuex
 ◯ CSS Pre-processors
 ◯ Linter / Formatter
 ◯ Unit Testing
 ◯ E2E Testing
? Use class-style component syntax? (Y/n) n

これで Vue.extend の環境が構築されます。簡単ですね。

Vue.extend における型

Vue.extend ベースでTypeScriptで書いていく際の型宣言を紹介していこうと思います。

props

Propについてはネイティブコンストラクターを付与することで、内部で型推論されます。
またArrayやObjectの詳細な型宣言については PropType を利用することで宣言することができます。

<script lang="ts">
  import Vue, { PropType } from "vue"

  export type PropObjType = {
    id: string
    index: number
  }

  export default Vue.extend({
    props: {
      val: {
        type: String,
        default: ""
      },
      obj: {
        type: Object as PropType<PropObjType>,
        default: () => ({
          id: "",
          index: 0
        })
      }
    }
  })
</script>

ここで注意が必要なのが、ビルド時のコンパイルエラーを得ることができないという点です。ただ実行時のエラーを得ることはできます。
また用意されているネイティブコンストラクターは以下の通りです。

  • String
  • Number
  • Boolean
  • Array
  • Object
  • Date
  • Function
  • Symbol

data

data()関数に向けて型を定義し、型アノテーションを付与します。

<script lang="ts">
  import Vue from "vue"

  export type DataType = {
    value: string
    enable: boolean
    count: number
  }

  export default Vue.extend({
    data(): DataType {
      return {
        value: "hoge",
        enable: true,
        count: 0
      }
    }
  })
</script>

lifecycle hooks

lifecycle hooksで着火するイベントは基本的に void 型の関数

<script lang="ts">
  import Vue from "vue"

  export default Vue.extend({
    created(): void {
      console.log("Created!!!")
    }
  })
</script>

computed

computedで呼び出される関数が返す値に対する型を宣言する

<script lang="ts">
  import Vue from "vue"

  export type DataType = {
    value: string
    enable: boolean
    count: number
  }

  export default Vue.extend({
    data(): DataType {
      return {
        value: "hoge",
        enable: true,
        count: 0
      }
    },

    computed: {
      isEnabled(): boolean {
        return this.enable
      },
      getCount(): number {
        return this.count
      }
    },
  })
</script>

methods

methodsで呼び出される関数が返す値に対する型を宣言する

<script lang="ts">
  import Vue from "vue"

  export type DataType = {
    value: string
    enable: boolean
    count: number
  }

  export default Vue.extend({
    data(): DataType {
      return {
        value: "hoge",
        enable: true,
        count: 0
      }
    },

    methods: {
      countUp(): void {
        this.count += 1
      },
      getValue(): string {
        return this.value
      }
    }
  })
</script>

まとめ

  • Vueらしさを保ちつつTypeScriptで書きたいって人 → Vue.extend
  • VueらしさよりTypeScriptらしく書きたいって人 → vue-property-decorator

という感じかなって思います。自分に合った方法でより楽しくVueを書いていきましょう!
ではまた!!!

257
182
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
257
182