Skip to content

Commit 47946f1

Browse files
authored
feat(language-core): unwrap __VLS_template & type support of useAttrs (#5106)
1 parent 2f98264 commit 47946f1

File tree

8 files changed

+123
-117
lines changed

8 files changed

+123
-117
lines changed

packages/language-core/lib/codegen/script/component.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ export function* generateComponent(
4141
yield generateSfcBlockSection(options.sfc.script, args.start + 1, args.end - 1, codeFeatures.all);
4242
}
4343
if (options.vueCompilerOptions.target >= 3.5 && options.templateCodegen?.templateRefs.size) {
44-
yield `__typeRefs: {} as __VLS_TemplateResult['refs'],${newLine}`;
44+
yield `__typeRefs: {} as __VLS_TemplateRefs,${newLine}`;
4545
}
4646
if (options.vueCompilerOptions.target >= 3.5 && options.templateCodegen?.singleRootElType) {
47-
yield `__typeEl: {} as __VLS_TemplateResult['rootEl'],${newLine}`;
47+
yield `__typeEl: {} as __VLS_TemplateEl,${newLine}`;
4848
}
4949
yield `})`;
5050
}
@@ -154,7 +154,7 @@ export function* generatePropsOption(
154154
});
155155
}
156156
if (inheritAttrs && options.templateCodegen?.inheritedAttrVars.size) {
157-
let attrsType = `__VLS_TemplateResult['attrs']`;
157+
let attrsType = `__VLS_TemplateAttrs`;
158158
if (hasEmitsOption) {
159159
attrsType = `Omit<${attrsType}, \`on\${string}\`>`;
160160
}

packages/language-core/lib/codegen/script/index.ts

-2
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,7 @@ export function* generateScript(options: ScriptCodegenOptions): Generator<Code,
151151
}
152152

153153
if (!ctx.generatedTemplate) {
154-
yield `function __VLS_template() {${newLine}`;
155154
const templateCodegenCtx = yield* generateTemplate(options, ctx);
156-
yield `}${endOfLine}`;
157155
yield* generateComponentSelf(options, ctx, templateCodegenCtx);
158156
}
159157

packages/language-core/lib/codegen/script/scriptSetup.ts

+16-20
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,10 @@ export function* generateScriptSetup(
6565
}
6666

6767
yield `return {} as {${newLine}`
68-
+ ` props: ${ctx.localTypes.PrettifyLocal}<__VLS_OwnProps & __VLS_PublicProps & __VLS_TemplateResult['attrs']> & __VLS_BuiltInPublicProps,${newLine}`
68+
+ ` props: ${ctx.localTypes.PrettifyLocal}<__VLS_OwnProps & __VLS_PublicProps & __VLS_TemplateAttrs> & __VLS_BuiltInPublicProps,${newLine}`
6969
+ ` expose(exposed: import('${options.vueCompilerOptions.lib}').ShallowUnwrapRef<${scriptSetupRanges.defineExpose ? 'typeof __VLS_exposed' : '{}'}>): void,${newLine}`
7070
+ ` attrs: any,${newLine}`
71-
+ ` slots: __VLS_TemplateResult['slots'],${newLine}`
71+
+ ` slots: __VLS_TemplateSlots,${newLine}`
7272
+ ` emit: ${emitTypes.length ? emitTypes.join(' & ') : `{}`},${newLine}`
7373
+ `}${endOfLine}`;
7474
yield `})(),${newLine}`; // __VLS_setup = (async () => {
@@ -170,18 +170,17 @@ function* generateSetupFunction(
170170
]);
171171
}
172172
}
173-
// TODO: circular reference
174-
// for (const { callExp } of scriptSetupRanges.useAttrs) {
175-
// setupCodeModifies.push([
176-
// [`(`],
177-
// callExp.start,
178-
// callExp.start
179-
// ], [
180-
// [` as __VLS_TemplateResult['attrs'] & Record<string, unknown>)`],
181-
// callExp.end,
182-
// callExp.end
183-
// ]);
184-
// }
173+
for (const { callExp } of scriptSetupRanges.useAttrs) {
174+
setupCodeModifies.push([
175+
[`(`],
176+
callExp.start,
177+
callExp.start
178+
], [
179+
[` as typeof __VLS_special.$attrs)`],
180+
callExp.end,
181+
callExp.end
182+
]);
183+
}
185184
for (const { callExp, exp, arg } of scriptSetupRanges.useCssModule) {
186185
setupCodeModifies.push([
187186
[`(`],
@@ -216,7 +215,7 @@ function* generateSetupFunction(
216215
callExp.start,
217216
callExp.start
218217
], [
219-
[` as __VLS_TemplateResult['slots'])`],
218+
[` as typeof __VLS_special.$slots)`],
220219
callExp.end,
221220
callExp.end
222221
]);
@@ -225,7 +224,7 @@ function* generateSetupFunction(
225224
for (const { callExp, exp, arg } of scriptSetupRanges.useTemplateRef) {
226225
const templateRefType = arg
227226
? [
228-
`__VLS_TemplateResult['refs'][`,
227+
`__VLS_TemplateRefs[`,
229228
generateSfcBlockSection(scriptSetup, arg.start, arg.end, codeFeatures.all),
230229
`]`
231230
]
@@ -294,19 +293,16 @@ function* generateSetupFunction(
294293

295294
yield* generateComponentProps(options, ctx, scriptSetup, scriptSetupRanges);
296295
yield* generateModelEmit(scriptSetup, scriptSetupRanges);
297-
yield `function __VLS_template() {${newLine}`;
298296
const templateCodegenCtx = yield* generateTemplate(options, ctx);
299-
yield `}${endOfLine}`;
300297
yield* generateComponentSelf(options, ctx, templateCodegenCtx);
301-
yield `type __VLS_TemplateResult = ReturnType<typeof __VLS_template>${endOfLine}`;
302298

303299
if (syntax) {
304300
if (!options.vueCompilerOptions.skipTemplateCodegen && (options.templateCodegen?.hasSlot || scriptSetupRanges.defineSlots)) {
305301
yield `const __VLS_component = `;
306302
yield* generateComponent(options, ctx, scriptSetup, scriptSetupRanges);
307303
yield endOfLine;
308304
yield `${syntax} `;
309-
yield `{} as ${ctx.localTypes.WithTemplateSlots}<typeof __VLS_component, __VLS_TemplateResult['slots']>${endOfLine}`;
305+
yield `{} as ${ctx.localTypes.WithTemplateSlots}<typeof __VLS_component, __VLS_TemplateSlots>${endOfLine}`;
310306
}
311307
else {
312308
yield `${syntax} `;

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

+4-6
Original file line numberDiff line numberDiff line change
@@ -131,12 +131,10 @@ function* generateTemplateBody(
131131
yield `const __VLS_rootEl = {} as any${endOfLine}`;
132132
}
133133

134-
yield `return {${newLine}`;
135-
yield ` attrs: {} as Partial<typeof __VLS_inheritedAttrs>,${newLine}`;
136-
yield ` slots: ${options.scriptSetupRanges?.defineSlots?.name ?? '__VLS_slots'},${newLine}`;
137-
yield ` refs: __VLS_refs,${newLine}`;
138-
yield ` rootEl: __VLS_rootEl,${newLine}`;
139-
yield `}${endOfLine}`;
134+
yield `type __VLS_TemplateAttrs = Partial<typeof __VLS_inheritedAttrs>${endOfLine}`;
135+
yield `type __VLS_TemplateSlots = typeof ${options.scriptSetupRanges?.defineSlots?.name ?? '__VLS_slots'}${endOfLine}`;
136+
yield `type __VLS_TemplateRefs = typeof __VLS_refs${endOfLine}`;
137+
yield `type __VLS_TemplateEl = typeof __VLS_rootEl${endOfLine}`;
140138
}
141139

142140
function* generateStyleScopedClasses(

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export function* generateTemplate(options: TemplateCodegenOptions): Generator<Co
4848
yield* generateStyleScopedClassReferences(ctx);
4949
const speicalTypes = [
5050
[slotsPropertyName, yield* generateSlots(options, ctx)],
51-
['$attrs', yield* generateInheritedAttrs(ctx)],
51+
['$attrs', yield* generateInheritedAttrs(options, ctx)],
5252
['$refs', yield* generateRefs(ctx)],
5353
['$el', yield* generateRootEl(ctx)]
5454
];
@@ -102,6 +102,7 @@ function* generateSlots(
102102
}
103103

104104
function* generateInheritedAttrs(
105+
options: TemplateCodegenOptions,
105106
ctx: TemplateCodegenContext
106107
): Generator<Code> {
107108
yield 'let __VLS_inheritedAttrs!: {}';
@@ -124,7 +125,7 @@ function* generateInheritedAttrs(
124125
}
125126
yield `]${endOfLine}`;
126127
}
127-
return `typeof __VLS_ctx.$attrs & Partial<typeof __VLS_inheritedAttrs>`;
128+
return `import('${options.vueCompilerOptions.lib}').ComponentPublicInstance['$attrs'] & Partial<typeof __VLS_inheritedAttrs>`;
128129
}
129130

130131
function* generateRefs(

packages/tsc/tests/__snapshots__/dts.spec.ts.snap

+72-84
Original file line numberDiff line numberDiff line change
@@ -617,27 +617,26 @@ export {};
617617
`;
618618
619619
exports[`vue-tsc-dts > Input: template-slots/component.vue, Output: template-slots/component.vue.d.ts 1`] = `
620-
"declare function __VLS_template(): {
621-
attrs: Partial<{}>;
622-
slots: {
623-
'no-bind'?(_: {}): any;
624-
default?(_: {
625-
num: number;
626-
}): any;
627-
'named-slot'?(_: {
628-
str: string;
629-
}): any;
630-
vbind?(_: {
631-
num: number;
632-
str: string;
633-
}): any;
634-
};
635-
refs: {};
636-
rootEl: any;
620+
"declare var __VLS_0: {};
621+
declare var __VLS_1: {
622+
num: number;
623+
};
624+
declare var __VLS_2: {
625+
str: string;
637626
};
638-
type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
627+
declare var __VLS_3: {
628+
num: number;
629+
str: string;
630+
};
631+
declare var __VLS_slots: {
632+
'no-bind'?(_: typeof __VLS_0): any;
633+
default?(_: typeof __VLS_1): any;
634+
'named-slot'?(_: typeof __VLS_2): any;
635+
vbind?(_: typeof __VLS_3): any;
636+
};
637+
type __VLS_TemplateSlots = typeof __VLS_slots;
639638
declare const __VLS_component: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
640-
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
639+
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateSlots>;
641640
export default _default;
642641
type __VLS_WithTemplateSlots<T, S> = T & {
643642
new (): {
@@ -649,39 +648,34 @@ type __VLS_WithTemplateSlots<T, S> = T & {
649648
650649
exports[`vue-tsc-dts > Input: template-slots/component-define-slots.vue, Output: template-slots/component-define-slots.vue.d.ts 1`] = `
651650
"import { VNode } from 'vue';
652-
declare function __VLS_template(): {
653-
attrs: Partial<{}>;
654-
slots: Readonly<{
655-
default: (props: {
656-
num: number;
657-
}) => VNode[];
658-
'named-slot': (props: {
659-
str: string;
660-
}) => VNode[];
661-
vbind: (props: {
662-
num: number;
663-
str: string;
664-
}) => VNode[];
665-
'no-bind': () => VNode[];
666-
}> & {
667-
default: (props: {
668-
num: number;
669-
}) => VNode[];
670-
'named-slot': (props: {
671-
str: string;
672-
}) => VNode[];
673-
vbind: (props: {
674-
num: number;
675-
str: string;
676-
}) => VNode[];
677-
'no-bind': () => VNode[];
678-
};
679-
refs: {};
680-
rootEl: any;
651+
declare const __VLS_slots: Readonly<{
652+
default: (props: {
653+
num: number;
654+
}) => VNode[];
655+
'named-slot': (props: {
656+
str: string;
657+
}) => VNode[];
658+
vbind: (props: {
659+
num: number;
660+
str: string;
661+
}) => VNode[];
662+
'no-bind': () => VNode[];
663+
}> & {
664+
default: (props: {
665+
num: number;
666+
}) => VNode[];
667+
'named-slot': (props: {
668+
str: string;
669+
}) => VNode[];
670+
vbind: (props: {
671+
num: number;
672+
str: string;
673+
}) => VNode[];
674+
'no-bind': () => VNode[];
681675
};
682-
type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
676+
type __VLS_TemplateSlots = typeof __VLS_slots;
683677
declare const __VLS_component: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
684-
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
678+
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateSlots>;
685679
export default _default;
686680
type __VLS_WithTemplateSlots<T, S> = T & {
687681
new (): {
@@ -692,23 +686,18 @@ type __VLS_WithTemplateSlots<T, S> = T & {
692686
`;
693687
694688
exports[`vue-tsc-dts > Input: template-slots/component-destructuring.vue, Output: template-slots/component-destructuring.vue.d.ts 1`] = `
695-
"declare function __VLS_template(): {
696-
attrs: Partial<{}>;
697-
slots: Readonly<{
698-
bottom: (props: {
699-
num: number;
700-
}) => any[];
701-
}> & {
702-
bottom: (props: {
703-
num: number;
704-
}) => any[];
705-
};
706-
refs: {};
707-
rootEl: any;
689+
"declare const __VLS_slots: Readonly<{
690+
bottom: (props: {
691+
num: number;
692+
}) => any[];
693+
}> & {
694+
bottom: (props: {
695+
num: number;
696+
}) => any[];
708697
};
709-
type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
698+
type __VLS_TemplateSlots = typeof __VLS_slots;
710699
declare const __VLS_component: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
711-
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
700+
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateSlots>;
712701
export default _default;
713702
type __VLS_WithTemplateSlots<T, S> = T & {
714703
new (): {
@@ -719,27 +708,26 @@ type __VLS_WithTemplateSlots<T, S> = T & {
719708
`;
720709
721710
exports[`vue-tsc-dts > Input: template-slots/component-no-script.vue, Output: template-slots/component-no-script.vue.d.ts 1`] = `
722-
"declare function __VLS_template(): {
723-
attrs: Partial<{}>;
724-
slots: {
725-
'no-bind'?(_: {}): any;
726-
default?(_: {
727-
num: number;
728-
}): any;
729-
'named-slot'?(_: {
730-
str: string;
731-
}): any;
732-
vbind?(_: {
733-
num: number;
734-
str: string;
735-
}): any;
736-
};
737-
refs: {};
738-
rootEl: any;
711+
"declare var __VLS_0: {};
712+
declare var __VLS_1: {
713+
num: number;
714+
};
715+
declare var __VLS_2: {
716+
str: string;
717+
};
718+
declare var __VLS_3: {
719+
num: number;
720+
str: string;
721+
};
722+
declare var __VLS_slots: {
723+
'no-bind'?(_: typeof __VLS_0): any;
724+
default?(_: typeof __VLS_1): any;
725+
'named-slot'?(_: typeof __VLS_2): any;
726+
vbind?(_: typeof __VLS_3): any;
739727
};
740-
type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
728+
type __VLS_TemplateSlots = typeof __VLS_slots;
741729
declare const __VLS_component: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
742-
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
730+
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateSlots>;
743731
export default _default;
744732
type __VLS_WithTemplateSlots<T, S> = T & {
745733
new (): {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<script setup lang="ts">
2+
import { useAttrs } from 'vue';
3+
import { exactType } from '../shared';
4+
5+
declare module 'vue' {
6+
interface ComponentCustomProperties {
7+
$attrs: {
8+
class: string
9+
};
10+
}
11+
}
12+
13+
type AttrsExact = Record<string, unknown> & { class: string } & Partial<{}>;
14+
15+
const attrs = useAttrs();
16+
exactType(attrs, {} as AttrsExact);
17+
</script>
18+
19+
<template>
20+
{{ exactType($attrs, {} as AttrsExact) }}
21+
</template>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"extends": "../../../tsconfig.base.json",
3+
"include": [ "**/*" ]
4+
}

0 commit comments

Comments
 (0)