Skip to content

Commit e6e8ae5

Browse files
authored
fix(language-core): infer template ref's type of native elements with v-for correctly (#4933)
1 parent 06f6f02 commit e6e8ae5

File tree

4 files changed

+23
-9
lines changed

4 files changed

+23
-9
lines changed

packages/language-core/lib/codegen/template/element.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,8 @@ export function* generateElement(
293293
ctx: TemplateCodegenContext,
294294
node: CompilerDOM.ElementNode,
295295
currentComponent: CompilerDOM.ElementNode | undefined,
296-
componentCtxVar: string | undefined
296+
componentCtxVar: string | undefined,
297+
isVForChild: boolean
297298
): Generator<Code> {
298299
const startTagOffset = node.loc.start.offset + options.template.content.substring(node.loc.start.offset).indexOf(node.tag);
299300
const endTagOffset = !node.isSelfClosing && options.template.lang === 'html'
@@ -350,7 +351,11 @@ export function* generateElement(
350351

351352
const [refName, offset] = yield* generateVScope(options, ctx, node, node.props);
352353
if (refName) {
353-
ctx.templateRefs.set(refName, [`__VLS_nativeElements['${node.tag}']`, offset!]);
354+
let refValue = `__VLS_nativeElements['${node.tag}']`;
355+
if (isVForChild) {
356+
refValue = `[${refValue}]`;
357+
}
358+
ctx.templateRefs.set(refName, [refValue, offset!]);
354359
}
355360
if (ctx.singleRootNode === node) {
356361
ctx.singleRootElType = `typeof __VLS_nativeElements['${node.tag}']`;

packages/language-core/lib/codegen/template/templateChild.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ export function* generateTemplateChild(
3131
node: CompilerDOM.RootNode | CompilerDOM.TemplateChildNode | CompilerDOM.SimpleExpressionNode,
3232
currentComponent: CompilerDOM.ElementNode | undefined,
3333
prevNode: CompilerDOM.TemplateChildNode | undefined,
34-
componentCtxVar: string | undefined
34+
componentCtxVar: string | undefined,
35+
isVForChild: boolean = false
3536
): Generator<Code> {
3637
if (prevNode?.type === CompilerDOM.NodeTypes.COMMENT) {
3738
const commentText = prevNode.content.trim().split(' ')[0];
@@ -82,7 +83,7 @@ export function* generateTemplateChild(
8283
node.tagType === CompilerDOM.ElementTypes.ELEMENT
8384
|| node.tagType === CompilerDOM.ElementTypes.TEMPLATE
8485
) {
85-
yield* generateElement(options, ctx, node, currentComponent, componentCtxVar);
86+
yield* generateElement(options, ctx, node, currentComponent, componentCtxVar, isVForChild);
8687
}
8788
else {
8889
yield* generateComponent(options, ctx, node, currentComponent);

packages/language-core/lib/codegen/template/vFor.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ export function* generateVFor(
8686
}
8787
let prev: CompilerDOM.TemplateChildNode | undefined;
8888
for (const childNode of node.children) {
89-
yield* generateTemplateChild(options, ctx, childNode, currentComponent, prev, componentCtxVar);
89+
yield* generateTemplateChild(options, ctx, childNode, currentComponent, prev, componentCtxVar, true);
9090
prev = childNode;
9191
}
9292
for (const varName of forBlockVars) {

test-workspace/tsc/passedFixtures/vue3/templateRef/template-ref.vue

+12-4
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,32 @@ if (comp1.value) {
77
exactType(comp1.value.foo, 1);
88
}
99
10-
const comp2 = useTemplateRef('v-for');
10+
const comp2 = useTemplateRef('v-for-generic');
1111
if (comp2.value) {
1212
exactType(comp2.value[0]?.foo, {} as number | undefined);
1313
}
1414
15-
const comp3 = useTemplateRef('a');
15+
const comp3 = useTemplateRef('native');
1616
if (comp3.value) {
1717
exactType(comp3.value.href, {} as string);
1818
}
19+
20+
const comp4 = useTemplateRef('v-for-native');
21+
if (comp4.value) {
22+
exactType(comp4.value[0]?.href, {} as string | undefined);
23+
}
1924
</script>
2025

2126
<template>
2227
<GenericGlobal ref="generic" :foo="1"/>
2328
{{ exactType(comp1?.foo, {} as 1 | undefined) }}
2429

25-
<GenericGlobal v-for="i in 4" ref="v-for" :foo="i"/>
30+
<GenericGlobal v-for="i in 4" ref="v-for-generic" :foo="i"/>
2631
{{ exactType(comp2?.[0]?.foo, {} as number | undefined) }}
2732

28-
<a ref="a"></a>
33+
<a ref="native"></a>
2934
{{ exactType(comp3?.href, {} as string | undefined) }}
35+
36+
<a v-for="i in 3" ref="v-for-native" :key="i"></a>
37+
{{ exactType(comp4?.[0]?.href, {} as string | undefined) }}
3038
</template>

0 commit comments

Comments
 (0)