Vue.js の v-slot でスロットのスコープ変数をなんとか推論させる
最近の Vetur では <template> 配下でも変数の型を確認できるようになってきましたが
スロットのスコープ変数については any になりがちです。
<template>
<div>
child
<slot :id="id" :namae="namae" />
</div>
</template>
<script>
export default {
data() {
return {
id: 1,
namae: 'Taro',
};
},
};
</script>
<template>
<div>
parent
<child>
<template v-slot="slotProps">
child 使用
{{ slotProps }}
</template>
</child>
</div>
</template>
<script>
import Child from './child.vue';
export default {
components: {
Child,
},
};
</script>
child 自身では template 中の変数の型を確認可能だが・・・
parent 側で使用した際の変数では any
実際の画面表示では slotProps の中身は id, namae を child にて指定した通り
これについて parent 側にて id などの型の確認ができないかなどをやってみます。
スロット側で変数を明確にする関数を定義して export
スロットを持つ child 側にて「何もしない」が型を明示する関数を用意してみます。
<script>
/**
* @typedef {Object<string, any>} SlotProps
* @property {number} id
* @property {string} namae
*/
/**
* @param {SlotProps} slotProps
* @return {SlotProps}
*/
export const vs = slotProps => slotProps;
export default {
data() {
return {
id: 1,
namae: 'Taro',
};
},
};
</script>
定義された関数 vs は引数に渡された値をそのまま返すだけのアロー関数です。
@typedef により型定義した SlotProps はそれぞれ child での <slot> に渡している要素と同一の構造のオブジェクトの定義となります。
使用側でスロット側で定義した変数用関数を適用
上記の vs を parent にて適用すると・・・
<template>
<div>
parent
<child>
<template v-slot="slotProps">
child 使用
{{ vs(slotProps) }}
{{ vs(slotProps).id }}
{{ vs(slotProps).namae }}
</template>
</child>
</div>
</template>
<script>
import Child, { vs } from './child.vue';
export default {
components: {
Child,
},
methods: {
vs,
},
};
</script>
child.vue より vs を import して parent の methods に追加しています。
これをエディタ上で確認してみると以下のようになります。
slotProps は相変わらず any
child より import した vs は定義した通りで推論されます。
vs(slotProps) の結果より生やした id は JSDoc で定義した通り number で確認できました。
(残念ながら vs(slotProps) の結果から .id などは候補としては取得できませんでした・・・)
JSDoc にて定義していない abababab を指定してみたところ
SlotProps 型に存在しない旨のメッセージが表示され、想定しないプロパティへのアクセスであることも確認できました。






