0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Nuxt】propsの型の曖昧さとその(応急的な)対処法

Last updated at Posted at 2022-04-29

初めに

普段から、Nuxt × TypeScriptでクライアントの開発をすることが多いのですが、
よく、propsでの型の曖昧さで苦しめられます

その際に、私が行う(応急的な)対処法について書いていきます

propsの型検査について

参照

プロパティを用いた子コンポーネントへのデータの受け渡し

型検査

型検査について

propsはいくつかの、組込みで型指定をすることができます

 props: {
   hoge: String
 }

また、ユーザー定義についてはPropTypeで型推論することができます

props: {
   hoge: {
     type: Object as Vue.PropType<THoge>
   }
}

上記の設定により、propsを受け取るComponent内では型を持ったpropsを使用することができます
スクリーンショット 2022-04-29 143233.png

また、親Componentから値を渡す際に、異なる型の値を渡すとエラーが確認できます

スクリーンショット 2022-04-29 143907.png

propsの型の曖昧さについて

上記のように型を定義することができればpropsを利用するComponent内では
TypeScriptの型のアシストを受けて実装するとができます

しかし、propsに対する型定義は厳密とは言えず
割となんでもやることができます、
なぜなら、親Componentでは子Componentでの定義を知らないので
v-bindまたは、v-modelにはどのような型のプロパティでも渡すことができてしまいます

例えば、下記の例では子ComponentではTHogeというObjectが渡されることを期待していますが、
親Componentではstring型を渡しています
この場合、Consoleにエラーが出力するものの、コンパイルエラーではないので騙せてしまいます

子Component

import Vue from 'vue'

type THoge = {
  hoge: string,
  hogehoge: number
}

export default Vue.extend({
  name: 'NuxtTutorial',
  props: {
    hoge: Object as Vue.PropType<THoge>
  },
  methods: {
    getHoge(): THoge {
      return this.hoge
    }
  }
})
</script>

親Component

export default Vue.extend({
  name: 'IndexPage',
  components: {
    Tutorial
  },
  data(){
    return {
      hoge: 
        hoge: "hoge"
    }
  }
})

Vue DevToolでporpsの中身を確認してもstringで渡せていることが確認できます

スクリーンショット 2022-04-29 144654.png

(応急的な)対処法

上記の型を騙せることを回避するために、普段は子Componentで定義したtypeを親で読み込んで定義することで
propsとして意図しない型を渡すことを防いでいます

子Component

import Vue from 'vue'

// typeもexport
export type THoge = {
  hoge: string,
  hogehoge: number
}

export default Vue.extend({
  name: 'NuxtTutorial',
  props: {
    hoge: Object as Vue.PropType<THoge>
  },
  methods: {
    getHoge(): THoge {
      return this.hoge
    }
  }
})
</script>

親Component


import Vue from 'vue'

// Vueとともにtypeもimport
import Tutorial, { THoge } from "~/components/Tutorial.vue"

type DataType = {
  hoge: THoge
}

export default Vue.extend({
  name: 'IndexPage',
  components: {
    Tutorial
  },
  data(): DataType {
    return {
      hoge: {
        hoge: "hoge",
        hogehoge: 1
      }
    }
  }
})

このように、子と親で同一の型定義をすることで意図しない型を渡すことを防いでいますが
この方法も確実とはいえず、このあたりが解消されないと、
VueでTypeScriptを使用するのは厳しいなという印象です

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?