Skip to content

Commit dd6c13e

Browse files
authored
fix(language-core): support defineModel for generic component (#4345)
1 parent 635f4fe commit dd6c13e

File tree

6 files changed

+60
-25
lines changed

6 files changed

+60
-25
lines changed

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

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,19 @@ export function* generateScriptSetup(
4646
+ ` __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>['expose'],${newLine}`
4747
+ ` __VLS_setup = (async () => {${newLine}`;
4848
yield* generateSetupFunction(options, ctx, scriptSetup, scriptSetupRanges, undefined, definePropMirrors);
49+
50+
const emitTypes = ['typeof __VLS_modelEmitsType'];
51+
52+
if (scriptSetupRanges.emits.define) {
53+
emitTypes.unshift(`typeof ${scriptSetupRanges.emits.name ?? '__VLS_emit'}`);
54+
}
55+
4956
yield ` return {} as {${newLine}`
5057
+ ` props: ${ctx.helperTypes.Prettify.name}<typeof __VLS_functionalComponentProps & __VLS_PublicProps> & __VLS_BuiltInPublicProps,${newLine}`
5158
+ ` expose(exposed: import('${options.vueCompilerOptions.lib}').ShallowUnwrapRef<${scriptSetupRanges.expose.define ? 'typeof __VLS_exposed' : '{}'}>): void,${newLine}`
5259
+ ` attrs: any,${newLine}`
5360
+ ` slots: ReturnType<typeof __VLS_template>,${newLine}`
54-
+ ` emit: typeof ${scriptSetupRanges.emits.name ?? '__VLS_emit'} & typeof __VLS_modelEmitsType,${newLine}`
61+
+ ` emit: ${emitTypes.join(' & ')},${newLine}`
5562
+ ` }${endOfLine}`;
5663
yield ` })(),${newLine}`; // __VLS_setup = (async () => {
5764
yield `) => ({} as import('${options.vueCompilerOptions.lib}').VNode & { __ctx?: Awaited<typeof __VLS_setup> }))`;
@@ -263,27 +270,25 @@ function* generateComponentProps(
263270
scriptSetupRanges: ScriptSetupRanges,
264271
definePropMirrors: Map<string, number>,
265272
): Generator<Code> {
266-
if (scriptSetupRanges.props.define?.arg || scriptSetupRanges.emits.define) {
267-
yield `const __VLS_fnComponent = `
268-
+ `(await import('${options.vueCompilerOptions.lib}')).defineComponent({${newLine}`;
269-
if (scriptSetupRanges.props.define?.arg) {
270-
yield ` props: `;
271-
yield generateSfcBlockSection(scriptSetup, scriptSetupRanges.props.define.arg.start, scriptSetupRanges.props.define.arg.end, codeFeatures.navigation);
272-
yield `,${newLine}`;
273-
}
273+
yield `const __VLS_fnComponent = `
274+
+ `(await import('${options.vueCompilerOptions.lib}')).defineComponent({${newLine}`;
275+
if (scriptSetupRanges.props.define?.arg) {
276+
yield ` props: `;
277+
yield generateSfcBlockSection(scriptSetup, scriptSetupRanges.props.define.arg.start, scriptSetupRanges.props.define.arg.end, codeFeatures.navigation);
278+
yield `,${newLine}`;
279+
}
280+
if (scriptSetupRanges.emits.define || scriptSetupRanges.defineProp.some(p => p.isModel)) {
281+
yield ` emits: ({} as __VLS_NormalizeEmits<typeof __VLS_modelEmitsType`;
274282
if (scriptSetupRanges.emits.define) {
275-
yield ` emits: ({} as __VLS_NormalizeEmits<typeof `;
283+
yield ` & typeof `;
276284
yield scriptSetupRanges.emits.name ?? '__VLS_emit';
277-
yield `>),${newLine}`;
278285
}
279-
yield `})${endOfLine}`;
280-
yield `let __VLS_functionalComponentProps!: `;
281-
yield `${ctx.helperTypes.OmitKeepDiscriminatedUnion.name}<InstanceType<typeof __VLS_fnComponent>['$props'], keyof __VLS_BuiltInPublicProps>`;
282-
yield endOfLine;
283-
}
284-
else {
285-
yield `let __VLS_functionalComponentProps!: {}${endOfLine}`;
286+
yield `>),${newLine}`;
286287
}
288+
yield `})${endOfLine}`;
289+
yield `let __VLS_functionalComponentProps!: `;
290+
yield `${ctx.helperTypes.OmitKeepDiscriminatedUnion.name}<InstanceType<typeof __VLS_fnComponent>['$props'], keyof __VLS_BuiltInPublicProps>`;
291+
yield endOfLine;
287292

288293
yield `type __VLS_BuiltInPublicProps =${newLine}`
289294
+ ` import('${options.vueCompilerOptions.lib}').VNodeProps${newLine}`

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

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,9 @@ type __VLS_Prettify<T> = {
7575
7676
exports[`vue-tsc-dts > Input: generic/component.vue, Output: generic/component.vue.d.ts 1`] = `
7777
"declare const _default: <T>(__VLS_props: {
78+
"onUpdate:title"?: (title: string) => any;
7879
onBar?: (data: number) => any;
80+
title?: string;
7981
foo: number;
8082
} & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, __VLS_ctx?: {
8183
slots: Readonly<{
@@ -88,12 +90,14 @@ exports[`vue-tsc-dts > Input: generic/component.vue, Output: generic/component.v
8890
}): any;
8991
};
9092
attrs: any;
91-
emit: (e: 'bar', data: number) => void;
93+
emit: ((e: 'bar', data: number) => void) & ((evt: "update:title", title: string) => void);
9294
}, __VLS_expose?: (exposed: import("vue").ShallowUnwrapRef<{
9395
baz: number;
9496
}>) => void, __VLS_setup?: Promise<{
9597
props: {
98+
"onUpdate:title"?: (title: string) => any;
9699
onBar?: (data: number) => any;
100+
title?: string;
97101
foo: number;
98102
} & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps;
99103
expose(exposed: import("vue").ShallowUnwrapRef<{
@@ -109,13 +113,15 @@ exports[`vue-tsc-dts > Input: generic/component.vue, Output: generic/component.v
109113
foo: number;
110114
}): any;
111115
};
112-
emit: (e: 'bar', data: number) => void;
116+
emit: ((e: 'bar', data: number) => void) & ((evt: "update:title", title: string) => void);
113117
}>) => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
114118
[key: string]: any;
115119
}> & {
116120
__ctx?: {
117121
props: {
122+
"onUpdate:title"?: (title: string) => any;
118123
onBar?: (data: number) => any;
124+
title?: string;
119125
foo: number;
120126
} & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps;
121127
expose(exposed: import("vue").ShallowUnwrapRef<{
@@ -131,7 +137,7 @@ exports[`vue-tsc-dts > Input: generic/component.vue, Output: generic/component.v
131137
foo: number;
132138
}): any;
133139
};
134-
emit: (e: 'bar', data: number) => void;
140+
emit: ((e: 'bar', data: number) => void) & ((evt: "update:title", title: string) => void);
135141
};
136142
};
137143
export default _default;
@@ -143,7 +149,9 @@ type __VLS_Prettify<T> = {
143149
144150
exports[`vue-tsc-dts > Input: generic/custom-extension-component.cext, Output: generic/custom-extension-component.cext.d.ts 1`] = `
145151
"declare const _default: <T>(__VLS_props: {
152+
"onUpdate:title"?: (title: string) => any;
146153
onBar?: (data: number) => any;
154+
title?: string;
147155
foo: number;
148156
} & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, __VLS_ctx?: {
149157
slots: Readonly<{
@@ -156,12 +164,14 @@ exports[`vue-tsc-dts > Input: generic/custom-extension-component.cext, Output: g
156164
}): any;
157165
};
158166
attrs: any;
159-
emit: (e: 'bar', data: number) => void;
167+
emit: ((e: 'bar', data: number) => void) & ((evt: "update:title", title: string) => void);
160168
}, __VLS_expose?: (exposed: import("vue").ShallowUnwrapRef<{
161169
baz: number;
162170
}>) => void, __VLS_setup?: Promise<{
163171
props: {
172+
"onUpdate:title"?: (title: string) => any;
164173
onBar?: (data: number) => any;
174+
title?: string;
165175
foo: number;
166176
} & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps;
167177
expose(exposed: import("vue").ShallowUnwrapRef<{
@@ -177,13 +187,15 @@ exports[`vue-tsc-dts > Input: generic/custom-extension-component.cext, Output: g
177187
foo: number;
178188
}): any;
179189
};
180-
emit: (e: 'bar', data: number) => void;
190+
emit: ((e: 'bar', data: number) => void) & ((evt: "update:title", title: string) => void);
181191
}>) => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
182192
[key: string]: any;
183193
}> & {
184194
__ctx?: {
185195
props: {
196+
"onUpdate:title"?: (title: string) => any;
186197
onBar?: (data: number) => any;
198+
title?: string;
187199
foo: number;
188200
} & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps;
189201
expose(exposed: import("vue").ShallowUnwrapRef<{
@@ -199,7 +211,7 @@ exports[`vue-tsc-dts > Input: generic/custom-extension-component.cext, Output: g
199211
foo: number;
200212
}): any;
201213
};
202-
emit: (e: 'bar', data: number) => void;
214+
emit: ((e: 'bar', data: number) => void) & ((evt: "update:title", title: string) => void);
203215
};
204216
};
205217
export default _default;
@@ -209,6 +221,12 @@ type __VLS_Prettify<T> = {
209221
"
210222
`;
211223
224+
exports[`vue-tsc-dts > Input: generic/main.vue, Output: generic/main.vue.d.ts 1`] = `
225+
"declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}>;
226+
export default _default;
227+
"
228+
`;
229+
212230
exports[`vue-tsc-dts > Input: non-component/component.ts, Output: non-component/component.d.ts 1`] = `
213231
"declare const _default: {};
214232
export default _default;

test-workspace/component-meta/generic/component.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ defineProps<{ foo: number }>();
33
defineEmits<{ (e: 'bar', data: number): void }>();
44
defineExpose({ baz: {} as number });
55
defineSlots<{ default?(data: { foo: number }): any }>();
6+
defineModel<string>('title');
67
</script>

test-workspace/component-meta/generic/custom-extension-component.cext

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ defineProps<{ foo: number }>();
33
defineEmits<{ (e: 'bar', data: number): void }>();
44
defineExpose({ baz: {} as number });
55
defineSlots<{ default?(data: { foo: number }): any }>();
6+
defineModel<string>('title');
67
</script>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<script setup lang="ts">
2+
import { ref } from 'vue';
3+
import Comp from './component.vue';
4+
5+
const title = ref('');
6+
</script>
7+
8+
<template>
9+
<Comp :foo="1" v-model:title="title" />
10+
</template>

test-workspace/tsc/vue3/defineProp_B/main.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ declare const ScriptSetupGenericExact: <T, >(
3131
} & import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps,
3232
attrs: any,
3333
slots: {},
34-
emit: any,
34+
emit: {},
3535
expose(_exposed: {}): void,
3636
}>
3737
) => import('vue').VNode & { __ctx?: Awaited<typeof _setup>; };

0 commit comments

Comments
 (0)