経緯
Vue.js-Challenges Prop Validationをやって間違えてしまった
この問題
他にも問題があるので興味ある人は是非やって見てください
条件:
- Propsで受け取る typeは 'primary' 'ghost' 'dashed' 'text' 'default' だけ
- typeのデフォ値は 'default'
- typeは必須Propsでない
- 'primary' 'ghost' 'dashed' 'text' 'default' 以外のものはValidationする
最初の間違えた解答
子Componentである
Button.vue
<script lang="ts" setup>
interface Props{
type?: 'primary' | 'ghost' | 'dashed' | 'text' | 'default';
}
const props = withDefaults(defineProps<Props>(),{
type: 'default'
})
</script>
<template>
<button :type="props.type">Button</button>
// わかりやすくするために表示している
<p>{{ props.type }}</p>
</template>
親コンポーネント
<script setup lang="ts">
import Button from './Button.vue';
</script>
<template>
<Button />
<br />
<Button type="primary" />
<br />
<Button type='unknown' />
</template>
一見綺麗に見えるし、表示上は問題ないように見えるが....
問題点
4.'primary' 'ghost' 'dashed' 'text' 'default' 以外のものはValidationする
この条件をクリアできていない。consoleにもwaringはでない。エディター上ではtypeを渡そうとしたときに補完は効くものの unknownにしたところでエディター上でもwarning等はでていない
なぜこのような解答にしたのか?
typescriptで型定義されているから指定外のものを渡した時には型errorなりwarningが出るなり勝手にやってくれると勘違いした。
解決法
型宣言を使用したdefinePropsの定義ではvalidateを入れるような方法を見つけられなかった
また、実行時の宣言と型宣言は同時に使えなかったので今回は型宣言を諦めて実行時の宣言にした
defineProps または defineEmits は、実行時の宣言か型宣言のどちらかしか使用できません。両方を同時に使用すると、コンパイルエラーになります。
<script lang="ts" setup>
import { PropType } from 'vue';
type ButtonType = 'primary' | 'ghost' | 'dashed' | 'text' | 'default';
const props = defineProps({
type: {
type: String as PropType<ButtonType>,
default: 'default',
validator: (value: ButtonType) => {
return ['primary', 'ghost', 'dashed', 'text', 'default'].includes(value);
},
},
});
</script>
<template>
<button :type="props.type">Button</button>
<p>{{ props.type }}</p>
</template>
親コンポーネントは変更なし
[結果]期待している通りwaringがconsoleで出た
[Vue warn]: Invalid prop: custom validator check failed for prop "type".
at <TestButton type="unknown" >
at <NotFound onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< undefined > >
at <RouterView>
at <SimpleLayout>
at <App>
実際にどのように使い分ければいいのかの自論
Propsの値をより厳密にしたいケースはValidationを含める
タイポミスでPropsの値が違っていることに気づかなかったりするメリットはあるものの、型宣言からのPropsの定義方法は非常に簡単で見やすい部分があるため、Propsの値を限定的なものにしたいケース以外はValidationを行わない。
ただ、より正確に書くにはValidationを含めた書き方の方が良さそう