I have two Vue components. For simplicity of this question I called them component A and component B.
Component A
<template>
<div>{{ recursive.text }} component A</div>
<component-b v-if="recursive.value" :recursive="recursive.value" />
</template>
<script lang="ts">
import { defineAsyncComponent, defineComponent } from 'vue';
export default defineComponent({
name: 'ComponentA',
components: {
ComponentB: defineAsyncComponent(() => import('./B.vue')),
},
});
</script>
<script lang="ts" setup>
interface RecursiveProp {
text: string;
value?: RecursiveProp;
}
const props = defineProps<{ recursive: RecursiveProp }>();
</script>
Component B
<template>
<div>{{ recursive.text }} component B</div>
<component-a v-if="recursive.value" :recursive="recursive.value" />
</template>
<script lang="ts">
import { defineAsyncComponent, defineComponent } from 'vue';
export default defineComponent({
name: 'ComponentB',
components: {
ComponentA: defineAsyncComponent(() => import('./A.vue')),
},
});
</script>
<script lang="ts" setup>
interface RecursiveProp {
text: string;
value?: RecursiveProp;
}
const props = defineProps<{ recursive: RecursiveProp }>();
</script>
For example, when I import Component A into another component and pass it the correct props, the code works with no errors showing in the browser. Component A and Component B recursively render the specified amount of times based on the given prop. But for some reason Visual Studio Code complains when the components reference to each other in this way. I attached a picture of the error below. This error is present in both component A and component B.
In the Vue documentation, this problem is referenced inside the Handling Edge Cases section. The only problem is that it is Vue 2 documentation: https://v2.vuejs.org/v2/guide/components-edge-cases.html#Circular-References-Between-Components
In Vue 3 you can use defineAsyncComponent. This makes my code work, but makes the error appear in Visual Studio code: https://vuejs.org/guide/components/async.html#async-components=
I am aware I can globally register one of the components. But that is something I want to avoid.
Is there a way to correctly circular reference components in Vue 3 with Typescript?
It seems this issue only affects <script lang="ts">
and is unrelated to the IDE or the <script setup lang="ts">
.
A workaround is to register the recursive async components in <script setup lang="ts">
instead of <script lang="ts">
:
<!-- A.vue -->
<template>
<div>{{ recursive.text }} component A</div>
<component-b v-if="recursive.value" :recursive="recursive.value" />
</template>
<script lang="ts" setup>
import { defineAsyncComponent } from 'vue'
👇
const ComponentB = defineAsyncComponent(() => import('./B.vue'))
interface RecursiveProp {
text: string;
value?: RecursiveProp;
}
const props = defineProps<{ recursive: RecursiveProp }>();
</script>
<!-- B.vue -->
<template>
<div>{{ rec.text }} component B</div>
<component-a v-if="rec.value" :recursive="rec.value" />
</template>
<script lang="ts" setup>
import { defineAsyncComponent, computed } from 'vue'
👇
const ComponentA = defineAsyncComponent(() => import('./A.vue'))
interface RecursiveProp {
text: string;
value?: RecursiveProp;
}
const props = defineProps<{ recursive: RecursiveProp }>();
// compute stop-condition for the recursion
const rec = computed(() => ({
...props.recursive,
value: undefined
} as RecursiveProp))
</script>
demo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With