Add `Slots` generic parameter to `DefineComponent`
What problem does this feature solve?
Currently, to define a Vue component with typed slots, you can't use DefineComponent
as the slots are manually set to Readonly<InternalSlots>
.
A hacky workaround is to use a generator function that returns defineComponent(...)
.
The return type of this generator function is a constructor type which tries to emulate DefineComponent
:
<script lang="tsx">
export createGenericListComponent<T extends { id: string }>(): {
new (): {
$props: {
items: T[]
}
$slots: {
default: ({ item }: { item: T }) => VNode[]
}
}
} {
return defineComponent({
props: {
items: Array as PropType<T[]>
},
setup(props, {slots}) {
return () => (
<ul>
{props.items.map((item) => (
<li key={item.id}>
{slots.default && slots.default({ item })}
</li>
))}
</ul>
)
}
})
}
</script>
What does the proposed API look like?
For manually setting the type:
export createGenericListComponent<T extends { id: string }>(): DefineComponent<
{ items: T[] }, // Props
{ default: ({ item }: { item: T }) => VNode[] } // Slots
>
In the future it would be awesome, if Slots
would be infered out of the template / render function.
Or a defineSlots<...>()
macro could be provided instead, like with defineProps<...>()
?
FYI Vue Macros implemented this feature.
https://vue-macros.sxzz.moe/macros/define-slots.html
relate RFC https://github.com/vuejs/core/pull/2693