Subscribe on changes!

Add `Slots` generic parameter to `DefineComponent`

avatar
May 19th 2022

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<...>()?

avatar
Jan 4th 2023

I also expect this feature to be implemented in the feature, especially slot can be infered out

avatar
Jan 4th 2023