language-tools: Cannot use `InstanceType>>` on generic components

Since the push of adding generic components on Vue 3.3.0, we don’t seem able to get the InstanceType aka public instance anymore.

<script setup lang="ts" generic="T">
const props = withDefaults(defineProps<{
	value?: T | null;
	list: T[];
}>(), {
	value: null,
});
</script>

<template>
    <select>
       // code
    </select>
</template>
<script lang="ts">
import MyComp from './MyComp.vue'

// This has error
const el = ref<null | InstanceType<typeof MyComp<any>>>( null )

</script>
<template>
   <my-comp ref="el" list="[]"/>
</template>

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 31
  • Comments: 19 (6 by maintainers)

Commits related to this issue

Most upvoted comments

This is my temporary solution, but it’s not perfect😂. I’m looking forward to the official release of the final solution.

import { type DefineComponent } from 'vue'
import MyComp from './MyComp.vue'

type ComponentInstance<T> = T extends new (...args: any[]) => infer R
  ? R
  : T extends (...args: any[]) => infer R
    ? R extends { __ctx?: infer K }
      ? Exclude<K, void> extends { expose: (...args: infer K) => void }
        ? K[0] & InstanceType<DefineComponent>
        : any
      : any
    : any

const el = ref<null | ComponentInstance<typeof MyComp<any>>>(null)

Hey folks 👋 Could you please checkout #3536? Does it work for you?

[!NOTE]
You should use ComponentExposed from the vue-component-type-helpers packages instead of TypeScript’s built-in ReturnType or InstanceType utilities.

Vue 3.3.4 Volar 1.7.8 Without generic and with InstanceType Screenshot_2

With generic and ReturnType/ComponentExposed Screenshot_1

For some reason, I am getting {} type from the ComponentExposed utility. Have any of you encountered something similar?

Hey guys, it’s really blocking the use of generic components, any chance that it will be fixed soon?

Thanks for the great tools btw 😃

Install vue-component-type-helpers, import { ComponentExposed } from 'vue-component-type-helpers', then replace InstanceType with ComponenttExposed.

@Bernard-Borg #3271, please be patient 😃

I have the same problem. Why this issue is closed?

Hey! how I’m supposed to do, when I want for example $el from a generic component?

When using generic, Volar defines the component as a functional component, so you should use ReturnType instead of InstanceType:

Another option is to use ComponentExposed from vue-component-type-helpers:

import MyComp from './MyComp.vue'
import type { ComponentExposed } from 'vue-component-type-helpers'

const el = ref<null | ComponentExposed<typeof MyComp<any>>>( null )