Reputation: 293
I'm trying to set types on my slot props to handle in a table component as you can see in the image
I also have been trying with
#body={item: UserItem}
, but it is only rename the parametter.
#body={<UserItem>item}
and #body={item<UserItem>}
, but it does not work
Upvotes: 20
Views: 19941
Reputation: 2263
The slot scope is an object so you need to type the object itself like
<template #body="{ item }: { item: UserItem }" />
But if the Table
component is your own component you could also use generic
in combination with defineProps
and defineSlots
to automatically infer the type for item
in your slot based on the values
prop that is passed in.
<script setup lang="ts" generic="T">
const props = defineProps<{
values: T[]
}>()
const slots = defineSlots<{
body(props: { item: T }): void
}>()
</script>
Upvotes: 39
Reputation: 497
You can do it with defineSlots
example:
// in yout template
<slot name="body" :msg="msg"></slot>
// in your script
defineSlots<{
body(props: { msg: string }): any
}>()
and with that you will have msg as a string type
Upvotes: 9
Reputation: 188
Creating element as a render function can help to resolve the issue because you won't need to deal with typescript inside Vue template. In render function you will be able to use types however you want.
Here is how your render function might look like:
<template>
<div>
<render />
</div>
</template>
<script setup lang="ts">
import {h} from "vue";
import {Table} from "...";
interface UserItem {
name: string;
id: string;
};
const values = {};
const render = () => {
return h(Table, {values: values, cols: ["Name", "id"]}, {
body: ({item}: {item: UserItem}) => [
h('th', item.name),
h('th', item.id)
],
});
};
</script>
P.S.
I haven't tested the code but I wrote similar code that worked in my case. See my another response related to this question: https://stackoverflow.com/a/75518154/5746474
Upvotes: 1