Today, I learned that when you use TypeScript with VueJS, you can create generic components to make them type-safe:

Generic type parameters can be declared using the generic attribute on the <script> tag:

<script setup lang="ts" generic="T">
defineProps<{
  items: T[]
  selected: T
}>()
</script>

The value of generic works exactly the same as the parameter list between <...> in TypeScript. For example, you can use multiple parameters, > extends constraints, default types, and reference imported types:

<script
  setup
  lang="ts"
  generic="T extends string | number, U extends Item"
>
import type { Item } from './types'
defineProps<{
  id: T
  list: U[]
}>()
</script>

In order to use a reference to a generic component in a ref you need to use the [vue-component-type-helpers](https://www.npmjs.com/package/> vue-component-type-helpers) library as InstanceType won't work.

<script
  setup
  lang="ts"
>
import componentWithoutGenerics from '../component-without-generics.vue';
import genericComponent from '../generic-component.vue';

import type { ComponentExposed } from 'vue-component-type-helpers';

// Works for a component without generics
ref<InstanceType<typeof componentWithoutGenerics>>();

ref<ComponentExposed<typeof genericComponent>>();

source