vuejs/language-tools

dynamic component not recognized

baojd42 opened this issue · 6 comments

I would like to use <component :is="name" /> .

The editor labels it with red color and the intellisense infers the type as any. No error messages prompted.
image

The code works fine. It seems this tag is not recognized by volar.

vue: 2.6.14
volar: 0.29.2
vscode: 1.62.0

this is expected, because component type is runtime determined, there is no way to infer component props before runtime.

@IWANABETHATGUY Should theoretically be possible if name has an explicit type

<template>
  <component :is="name" prop-that-only-exists-on-the-somecomponent="hello"/> <!-- should throw error since prop-that-only-exists-on-the-somecomponent cannot be found on OtherComponent -->
  <button @click="setSome()">Render Some Component</button>
  <button @click="setOther()" >Render Other Component</button>
</template>
<script setup lang="ts">
import SomeComponent from './SomeComponent.vue'
import OtherComponent from './OtherComponent.vue'
const setSome = () => { name.value = SomeComponent }
const setOther = () => { name.value = OtherComponent }

const name = ref<typeof SomeComponent | typeof OtherComponent>(SomeComponent)
</script>

@IWANABETHATGUY Thanks for your reply. If <component> being any is expected, then I can live with that. But it is highlighted the same as a not imported component. That is a bit annoying.
image
I noticed in the docs, <component> and <slot> are both component-like feature of template syntax. Should they be highlighted the same way?

@IWANABETHATGUY Should theoretically be possible if name has an explicit type

<template>
  <component :is="name" prop-that-only-exists-on-the-somecomponent="hello"/> <!-- should throw error since prop-that-only-exists-on-the-somecomponent cannot be found on OtherComponent -->
  <button @click="setSome()">Render Some Component</button>
  <button @click="setOther()" >Render Other Component</button>
</template>
<script setup lang="ts">
import SomeComponent from './SomeComponent.vue'
import OtherComponent from './OtherComponent.vue'
const setSome = () => { name.value = SomeComponent }
const setOther = () => { name.value = OtherComponent }

const name = ref<typeof SomeComponent | typeof OtherComponent>(SomeComponent)
</script>

It would be great if this could be implemented.

You can already define it yourself.

declare module '@vue/runtime-dom' {
	export interface GlobalComponents {
		component: <T>(props: { is: T } & ExtractComponentProps<T>) => JSX.Element
	}
}

type ExtractComponentProps<T> = T extends new (...args: any) => { $props: infer P } ? P : {};

export { }

螢幕截圖 2021-11-11 上午2 15 08

Duplicate of #482