diff --git a/packages/vue-code-gen/src/generators/template.ts b/packages/vue-code-gen/src/generators/template.ts index cdc4a3ad1..2da5c4e8f 100644 --- a/packages/vue-code-gen/src/generators/template.ts +++ b/packages/vue-code-gen/src/generators/template.ts @@ -86,7 +86,6 @@ export function generate( slotsComponent: string, emit: string, slots: string, - events: Record, offsets: number[], }> = {}; const localVars: Record = {}; @@ -110,7 +109,6 @@ export function generate( const var_slotsComponent = `__VLS_${elementIndex++}`; const var_emit = `__VLS_${elementIndex++}`; const var_slots = `__VLS_${elementIndex++}`; - const var_events: Record = {}; if (isNamespacedTag) { for (let i = 0; i < tagRanges.length; i++) { @@ -141,26 +139,6 @@ export function generate( tsCodeGen.addText(`declare const ${var_emit}: __VLS_types.ExtractEmit2;\n`); tsCodeGen.addText(`declare const ${var_slots}: __VLS_types.DefaultSlots;\n`); - for (const eventName in tag.events) { - - const var_on = `__VLS_${elementIndex++}`; - const key_1 = eventName; // click-outside - const key_3 = camelize(key_1); // clickOutside - - tsCodeGen.addText(`type ${var_on} = \n`); - if (key_1 !== key_3) { - tsCodeGen.addText(`__VLS_types.FirstFunction<\n`); - tsCodeGen.addText(`__VLS_types.EmitEvent,\n`); - tsCodeGen.addText(`__VLS_types.EmitEvent\n`); - tsCodeGen.addText(`>;\n`); - } - else { - tsCodeGen.addText(`__VLS_types.EmitEvent;\n`); - } - - var_events[eventName] = var_on; - } - const name1 = tagName; // hello-world const name2 = camelize(tagName); // helloWorld const name3 = name2[0].toUpperCase() + name2.slice(1); // HelloWorld @@ -232,7 +210,6 @@ export function generate( slotsComponent: var_slotsComponent, emit: var_emit, slots: var_slots, - events: var_events, offsets: tag.offsets.map(offset => htmlToTemplate(offset, offset)?.start).filter(notEmpty), }; } @@ -625,16 +602,21 @@ export function generate( tryWriteInstance(); + const varInstanceProps = `__VLS_${elementIndex++}`; + + tsCodeGen.addText(`type ${varInstanceProps} = typeof ${varComponentInstance} extends { $props: infer Props } ? Props & Omit<__VLS_types.GlobalAttrs, keyof Props> & Record : typeof ${tagResolves[node.tag].rawComponent} & Record;\n`); tsCodeGen.addText(`const __VLS_${elementIndex++}: {\n`); tsCodeGen.addText(`'${prop.arg.loc.source}': __VLS_types.FillingEventArg<\n`); { tsCodeGen.addText(`__VLS_types.FirstFunction<\n`); { - tsCodeGen.addText(`__VLS_types.FirstFunction<\n`); - tsCodeGen.addText(`${tagResolves[node.tag].events[prop.arg.loc.source]},\n`); + tsCodeGen.addText(`__VLS_types.EmitEvent,\n`); { - tsCodeGen.addText(`(typeof ${varComponentInstance} extends { $props: infer Props } ? Props & Omit<__VLS_types.GlobalAttrs, keyof Props> & Record : typeof ${tagResolves[node.tag].rawComponent} & Record)[`); + const key_2 = camelize('on-' + prop.arg.loc.source); // onClickOutside + const key_3 = 'on' + prop.arg.loc.source[0].toUpperCase() + prop.arg.loc.source.substring(1); // onClick-outside + + tsCodeGen.addText(`${varInstanceProps}[`); writeCodeWithQuotes( key_2, [{ start: prop.arg.loc.start.offset, end: prop.arg.loc.end.offset }], @@ -653,23 +635,32 @@ export function generate( }, }, ); - tsCodeGen.addText(`]\n`); - } - tsCodeGen.addText(`>,\n`); - - const camelizeName = camelize(prop.arg.loc.source); - - if (camelizeName === prop.arg.loc.source) { - tsCodeGen.addText(`typeof ${varComponentInstance} extends { $emit: infer Emit } ? __VLS_types.EmitEvent2 : unknown,\n`); - } - else { - tsCodeGen.addText(`__VLS_types.FirstFunction<\n`); - { - tsCodeGen.addText(`typeof ${varComponentInstance} extends { $emit: infer Emit } ? __VLS_types.EmitEvent2 : unknown,\n`); - tsCodeGen.addText(`typeof ${varComponentInstance} extends { $emit: infer Emit } ? __VLS_types.EmitEvent2 : unknown,\n`); + tsCodeGen.addText(`],\n`); + + if (key_3 !== key_2) { + tsCodeGen.addText(`${varInstanceProps}[`); + writeCodeWithQuotes( + key_3, + [{ start: prop.arg.loc.start.offset, end: prop.arg.loc.end.offset }], + { + vueTag: 'template', + capabilities: capabilitiesSet.attrReference, + normalizeNewName(newName) { + return 'on' + newName[0].toUpperCase() + newName.substring(1); + }, + applyNewName(oldName, newName) { + const hName = hyphenate(newName); + if (hyphenate(newName).startsWith('on-')) { + return camelize(hName.slice('on-'.length)); + } + return newName; + }, + }, + ); + tsCodeGen.addText(`],\n`); } - tsCodeGen.addText(`>\n`); } + tsCodeGen.addText(`typeof ${varComponentInstance} extends { $emit: infer Emit } ? __VLS_types.EmitEvent2 : unknown,\n`); } tsCodeGen.addText(`>\n`); } diff --git a/packages/vue-language-service/testCases/typeChecks/events.vue b/packages/vue-language-service/testCases/typeChecks/events.vue index 1efe2db12..c2aaecac2 100644 --- a/packages/vue-language-service/testCases/typeChecks/events.vue +++ b/packages/vue-language-service/testCases/typeChecks/events.vue @@ -1,13 +1,13 @@ @@ -31,7 +34,7 @@ import { defineComponent, FunctionalComponent, PropType } from 'vue'; import { exactType } from './shared'; import C5 from './events_union.vue'; -const C1 = defineComponent({ emits: { fooBar: (_num: number) => true } }); +const C1 = defineComponent({ emits: { fooBar: (_num: number) => true, 'bar-baz': (_num: number) => true } }); const C2 = defineComponent({ props: { onFooBar: {} as PropType<(num: number) => void> } }); const C6 = defineComponent({ props: { onFoo: {} as PropType<(_num: string) => void> }, emits: { foo: (_num: number) => true } }); const C7 = defineComponent({ emits: { click: (_num: number) => true } }); @@ -39,10 +42,13 @@ const C8 = defineComponent({ props: { onClick: {} as PropType<(_num: number) => diff --git a/packages/vue-typescript/src/utils/localTypes.ts b/packages/vue-typescript/src/utils/localTypes.ts index 7f5408772..453a77f17 100644 --- a/packages/vue-typescript/src/utils/localTypes.ts +++ b/packages/vue-typescript/src/utils/localTypes.ts @@ -119,9 +119,12 @@ export type EmitEvent_3 = : E2 extends AnyArray ? (E extends K ? (...args: any) => void : unknown) // emits: ['event-1', 'event-2'] : E extends keyof E2 ? ReturnVoid // emits: { 'event-1': () => true, 'event-2': () => true } : unknown -export type FirstFunction = +export type FirstFunction = NonNullable extends (Function | AnyArray) ? F0 : - NonNullable extends (Function | AnyArray) ? F1 : unknown; + NonNullable extends (Function | AnyArray) ? F1 : + NonNullable extends (Function | AnyArray) ? F2 : + NonNullable extends (Function | AnyArray) ? F3 : + unknown; export type GlobalAttrsBase = VNodeProps & AllowedComponentProps; export type GlobalAttrs = GlobalAttrsBase & HTMLAttributes; export type PickComponents = ComponentKeys extends keyof T ? Pick> : T;