初めに
普段から、Nuxt × TypeScriptでクライアントの開発をすることが多いのですが、
よく、propsでの型の曖昧さで苦しめられます
その際に、私が行う(応急的な)対処法について書いていきます
propsの型検査について
参照
プロパティを用いた子コンポーネントへのデータの受け渡し
型検査について
propsはいくつかの、組込みで型指定をすることができます
props: {
hoge: String
}
また、ユーザー定義についてはPropType
で型推論することができます
props: {
hoge: {
type: Object as Vue.PropType<THoge>
}
}
上記の設定により、propsを受け取るComponent内では型を持ったpropsを使用することができます
また、親Componentから値を渡す際に、異なる型の値を渡すとエラーが確認できます
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で渡せていることが確認できます
(応急的な)対処法
上記の型を騙せることを回避するために、普段は子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を使用するのは厳しいなという印象です