From f043b32fbb3ec924f3a3f6298eebfdd870ab8298 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 26 Sep 2023 01:23:04 +0800 Subject: [PATCH] fix: inherit emits props (#3533) Co-authored-by: Johnson Chu --- .../src/generators/script.ts | 56 +++++++++---- .../non-strict-template/#3289/Comp.vue | 5 ++ .../non-strict-template/#3289/main.tsx | 4 + .../non-strict-template/#3379/Comp.vue | 11 +++ .../non-strict-template/#3379/main.vue | 8 ++ .../non-strict-template/#3476/Comp.vue | 5 ++ .../non-strict-template/#3476/main.vue | 8 ++ .../non-strict-template/components/main.vue | 7 +- .../non-strict-template/defineProp_B/main.vue | 12 +-- .../tests/__snapshots__/dts.spec.ts.snap | 80 ++++++++++++------- 10 files changed, 142 insertions(+), 54 deletions(-) create mode 100644 packages/vue-test-workspace/vue-tsc/non-strict-template/#3289/Comp.vue create mode 100644 packages/vue-test-workspace/vue-tsc/non-strict-template/#3289/main.tsx create mode 100644 packages/vue-test-workspace/vue-tsc/non-strict-template/#3379/Comp.vue create mode 100644 packages/vue-test-workspace/vue-tsc/non-strict-template/#3379/main.vue create mode 100644 packages/vue-test-workspace/vue-tsc/non-strict-template/#3476/Comp.vue create mode 100644 packages/vue-test-workspace/vue-tsc/non-strict-template/#3476/main.vue diff --git a/packages/vue-language-core/src/generators/script.ts b/packages/vue-language-core/src/generators/script.ts index 3d89295656..62020cc4d0 100644 --- a/packages/vue-language-core/src/generators/script.ts +++ b/packages/vue-language-core/src/generators/script.ts @@ -73,7 +73,7 @@ export function generate( const bypassDefineComponent = lang === 'js' || lang === 'jsx'; const usedHelperTypes = { DefinePropsToOptions: false, - mergePropDefaults: false, + MergePropDefaults: false, WithTemplateSlots: false, PropsChildren: false, }; @@ -119,7 +119,7 @@ export function generate( codes.push(`type __VLS_TypePropsToRuntimeProps = { [K in keyof T]-?: {} extends Pick ? { type: import('${vueCompilerOptions.lib}').PropType<__VLS_NonUndefinedable> } : { type: import('${vueCompilerOptions.lib}').PropType, required: true } };\n`); } } - if (usedHelperTypes.mergePropDefaults) { + if (usedHelperTypes.MergePropDefaults) { codes.push(`type __VLS_WithDefaults = { // use 'keyof Pick' instead of 'keyof P' to keep props jsdoc [K in keyof Pick]: K extends keyof D ? __VLS_Prettify`); codes.push('(\n'); - codes.push( - `__VLS_props: Awaited['props']`, - `& import('${vueCompilerOptions.lib}').VNodeProps`, - `& import('${vueCompilerOptions.lib}').AllowedComponentProps`, - `& import('${vueCompilerOptions.lib}').ComponentCustomProps,\n`, - ); - codes.push(`__VLS_ctx?: Pick, 'attrs' | 'emit' | 'slots'>,\n`); + codes.push(`__VLS_props: Awaited['props'],\n`); + codes.push(`__VLS_ctx?: __VLS_Prettify, 'attrs' | 'emit' | 'slots'>>,\n`); // use __VLS_Prettify for less dts code codes.push(`__VLS_expose?: NonNullable>['expose'],\n`); codes.push('__VLS_setup = (async () => {\n'); scriptSetupGeneratedOffset = generateSetupFunction(true, 'none', definePropMirrors); //#region props + codes.push(`const __VLS_fnComponent = `); + codes.push(`(await import('${vueCompilerOptions.lib}')).defineComponent({\n`); + if (scriptSetupRanges.propsRuntimeArg) { + codes.push(`props: `); + addExtraReferenceVirtualCode('scriptSetup', scriptSetupRanges.propsRuntimeArg.start, scriptSetupRanges.propsRuntimeArg.end); + codes.push(`,\n`); + + } + if (scriptSetupRanges.defineEmits) { + codes.push( + `emits: ({} as __VLS_NormalizeEmits),\n`, + ); + } + codes.push(`});\n`); if (scriptSetupRanges.defineProp.length) { codes.push(`const __VLS_defaults = {\n`); for (const defineProp of scriptSetupRanges.defineProp) { @@ -322,10 +333,7 @@ export function generate( } codes.push(`};\n`); } - codes.push(`let __VLS_props!: {}`); - if (scriptSetupRanges.propsRuntimeArg) { - codes.push(` & InstanceType['$props']`); - } + codes.push(`let __VLS_fnPropsTypeOnly!: {}`); // TODO: reuse __VLS_fnPropsTypeOnly even without generic, and remove __VLS_propsOption_defineProp if (scriptSetupRanges.propsTypeArg) { codes.push(` & `); addVirtualCode('scriptSetup', scriptSetupRanges.propsTypeArg.start, scriptSetupRanges.propsTypeArg.end); @@ -355,15 +363,29 @@ export function generate( } codes.push(`}`); } + codes.push(`;\n`); + codes.push(`let __VLS_fnPropsDefineComponent!: InstanceType['$props']`); + codes.push(`;\n`); + codes.push(`let __VLS_fnPropsSlots!: `); if (scriptSetupRanges.defineSlots && vueCompilerOptions.jsxSlots) { usedHelperTypes.PropsChildren = true; - codes.push(` & __VLS_PropsChildren`); + codes.push(`__VLS_PropsChildren`); + } + else { + codes.push(`{}`); } codes.push(`;\n`); + codes.push( + `let __VLS_defaultProps!: `, + `import('${vueCompilerOptions.lib}').VNodeProps`, + `& import('${vueCompilerOptions.lib}').AllowedComponentProps`, + `& import('${vueCompilerOptions.lib}').ComponentCustomProps`, + `;\n`, + ); //#endregion codes.push('return {} as {\n'); - codes.push(`props: typeof __VLS_props,\n`); + codes.push(`props: __VLS_Prettify> & typeof __VLS_fnPropsSlots & typeof __VLS_defaultProps,\n`); codes.push(`expose(exposed: ${scriptSetupRanges.exposeRuntimeArg ? 'typeof __VLS_exposed' : '{}'}): void,\n`); codes.push('attrs: any,\n'); codes.push('slots: ReturnType,\n'); @@ -596,13 +618,13 @@ declare function defineProp(value?: T | (() => T), required?: boolean, rest?: codes.push('...{} as '); if (scriptSetupRanges.withDefaultsArg) { - usedHelperTypes.mergePropDefaults = true; + usedHelperTypes.MergePropDefaults = true; codes.push(`__VLS_WithDefaults<`); } codes.push(`__VLS_TypePropsToRuntimeProps<`); if (functional) { - codes.push(`typeof __VLS_props`); + codes.push(`typeof __VLS_fnPropsTypeOnly`); } else { addExtraReferenceVirtualCode('scriptSetup', scriptSetupRanges.propsTypeArg.start, scriptSetupRanges.propsTypeArg.end); diff --git a/packages/vue-test-workspace/vue-tsc/non-strict-template/#3289/Comp.vue b/packages/vue-test-workspace/vue-tsc/non-strict-template/#3289/Comp.vue new file mode 100644 index 0000000000..a1629b337a --- /dev/null +++ b/packages/vue-test-workspace/vue-tsc/non-strict-template/#3289/Comp.vue @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/packages/vue-test-workspace/vue-tsc/non-strict-template/#3289/main.tsx b/packages/vue-test-workspace/vue-tsc/non-strict-template/#3289/main.tsx new file mode 100644 index 0000000000..d958a59d16 --- /dev/null +++ b/packages/vue-test-workspace/vue-tsc/non-strict-template/#3289/main.tsx @@ -0,0 +1,4 @@ +import { exactType } from 'vue-tsc/shared'; +import Comp from './Comp.vue'; + + exactType(s, '' as string)} />; diff --git a/packages/vue-test-workspace/vue-tsc/non-strict-template/#3379/Comp.vue b/packages/vue-test-workspace/vue-tsc/non-strict-template/#3379/Comp.vue new file mode 100644 index 0000000000..17e49877fb --- /dev/null +++ b/packages/vue-test-workspace/vue-tsc/non-strict-template/#3379/Comp.vue @@ -0,0 +1,11 @@ + diff --git a/packages/vue-test-workspace/vue-tsc/non-strict-template/#3379/main.vue b/packages/vue-test-workspace/vue-tsc/non-strict-template/#3379/main.vue new file mode 100644 index 0000000000..ae1f5b1b04 --- /dev/null +++ b/packages/vue-test-workspace/vue-tsc/non-strict-template/#3379/main.vue @@ -0,0 +1,8 @@ + + + diff --git a/packages/vue-test-workspace/vue-tsc/non-strict-template/#3476/Comp.vue b/packages/vue-test-workspace/vue-tsc/non-strict-template/#3476/Comp.vue new file mode 100644 index 0000000000..e047280e9a --- /dev/null +++ b/packages/vue-test-workspace/vue-tsc/non-strict-template/#3476/Comp.vue @@ -0,0 +1,5 @@ + diff --git a/packages/vue-test-workspace/vue-tsc/non-strict-template/#3476/main.vue b/packages/vue-test-workspace/vue-tsc/non-strict-template/#3476/main.vue new file mode 100644 index 0000000000..c88a866926 --- /dev/null +++ b/packages/vue-test-workspace/vue-tsc/non-strict-template/#3476/main.vue @@ -0,0 +1,8 @@ + + + diff --git a/packages/vue-test-workspace/vue-tsc/non-strict-template/components/main.vue b/packages/vue-test-workspace/vue-tsc/non-strict-template/components/main.vue index 96fea1cda0..44db275ee4 100644 --- a/packages/vue-test-workspace/vue-tsc/non-strict-template/components/main.vue +++ b/packages/vue-test-workspace/vue-tsc/non-strict-template/components/main.vue @@ -66,11 +66,14 @@ const ScriptSetupDefaultPropsExact = defineComponent({ }); // vue 3.3 generic declare const ScriptSetupGenericExact: ( - _props: NonNullable>['props'] & import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, + _props: NonNullable>['props'], _ctx?: Pick>, 'attrs' | 'emit' | 'slots'>, _expose?: NonNullable>['expose'], _setup?: Promise<{ - props: { foo: T; } & { [K in keyof JSX.ElementChildrenAttribute]?: Readonly<{ default?(data: T): any; }> }, + props: { $children?: Readonly<{ default?(data: T): any; }>; } & { + onBar?: ((data: T) => any) | undefined; + foo: T; + } & import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, attrs: any, slots: Readonly<{ default?(data: T): any; }>, emit: { (e: 'bar', data: T): void; }, diff --git a/packages/vue-test-workspace/vue-tsc/non-strict-template/defineProp_B/main.vue b/packages/vue-test-workspace/vue-tsc/non-strict-template/defineProp_B/main.vue index b4a7ff5059..ab57c73fc2 100644 --- a/packages/vue-test-workspace/vue-tsc/non-strict-template/defineProp_B/main.vue +++ b/packages/vue-test-workspace/vue-tsc/non-strict-template/defineProp_B/main.vue @@ -7,11 +7,11 @@ import ScriptSetupGeneric from './script-setup-generic.vue'; const ScriptSetupExact = defineComponent({ props: {} as { a: PropType; - b: { type: PropType, required: true }; - c: { type: PropType, required: true }; + b: { type: PropType, required: true; }; + c: { type: PropType, required: true; }; d: PropType; e: PropType; - f: { type: PropType, required: true }; + f: { type: PropType, required: true; }; g: PropType; }, setup() { @@ -19,7 +19,7 @@ const ScriptSetupExact = defineComponent({ }, }); declare const ScriptSetupGenericExact: ( - _props: NonNullable>['props'] & import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, + _props: NonNullable>['props'], _ctx?: Pick>, 'attrs' | 'emit' | 'slots'>, _expose?: NonNullable>['expose'], _setup?: Promise<{ @@ -28,13 +28,13 @@ declare const ScriptSetupGenericExact: ( b?: T | undefined; c?: T | undefined; d: T; - }, + } & import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, attrs: any, slots: {}, emit: any, expose(_exposed: {}): void, }> -) => import('vue').VNode & { __ctx?: Awaited }; +) => import('vue').VNode & { __ctx?: Awaited; }; exactType(ScriptSetup, ScriptSetupExact); exactType(ScriptSetupGeneric, ScriptSetupGenericExact); diff --git a/packages/vue-tsc/tests/__snapshots__/dts.spec.ts.snap b/packages/vue-tsc/tests/__snapshots__/dts.spec.ts.snap index 72e11c8466..551c80aeaa 100644 --- a/packages/vue-tsc/tests/__snapshots__/dts.spec.ts.snap +++ b/packages/vue-tsc/tests/__snapshots__/dts.spec.ts.snap @@ -86,25 +86,21 @@ export default _default; exports[`vue-tsc-dts > Input: components/script-setup-generic.vue, Output: components/script-setup-generic.vue.d.ts 1`] = ` "declare const _default: (__VLS_props: { + onBar?: (data: T) => any; foo: T; -} & import(\\"vue\\").VNodeProps & import(\\"vue\\").AllowedComponentProps & import(\\"vue\\").ComponentCustomProps, __VLS_ctx?: Pick<{ - props: { - foo: T; - }; - expose(exposed: { - baz: T; - }): void; - attrs: any; +} & import(\\"vue\\").VNodeProps & import(\\"vue\\").AllowedComponentProps & import(\\"vue\\").ComponentCustomProps, __VLS_ctx?: { slots: Readonly<{ default?(data: T): any; }>; + attrs: any; emit: (e: 'bar', data: T) => void; -}, \\"slots\\" | \\"attrs\\" | \\"emit\\">, __VLS_expose?: (exposed: { +}, __VLS_expose?: (exposed: { baz: T; }) => void, __VLS_setup?: Promise<{ props: { + onBar?: (data: T) => any; foo: T; - }; + } & import(\\"vue\\").VNodeProps & import(\\"vue\\").AllowedComponentProps & import(\\"vue\\").ComponentCustomProps; expose(exposed: { baz: T; }): void; @@ -118,8 +114,9 @@ exports[`vue-tsc-dts > Input: components/script-setup-generic.vue, Output: compo }> & { __ctx?: { props: { + onBar?: (data: T) => any; foo: T; - }; + } & import(\\"vue\\").VNodeProps & import(\\"vue\\").AllowedComponentProps & import(\\"vue\\").ComponentCustomProps; expose(exposed: { baz: T; }): void; @@ -289,28 +286,21 @@ export default _default; exports[`vue-tsc-dts > Input: defineProp_B/script-setup-generic.vue, Output: defineProp_B/script-setup-generic.vue.d.ts 1`] = ` "declare const _default: (__VLS_props: { - a?: T; - b?: T; c?: T; d: T; -} & import(\\"vue\\").VNodeProps & import(\\"vue\\").AllowedComponentProps & import(\\"vue\\").ComponentCustomProps, __VLS_ctx?: Pick<{ - props: { - a?: T; - b?: T; - c?: T; - d: T; - }; - expose(exposed: {}): void; - attrs: any; + a?: T; + b?: T; +} & import(\\"vue\\").VNodeProps & import(\\"vue\\").AllowedComponentProps & import(\\"vue\\").ComponentCustomProps, __VLS_ctx?: { slots: {}; + attrs: any; emit: any; -}, \\"slots\\" | \\"attrs\\" | \\"emit\\">, __VLS_expose?: (exposed: {}) => void, __VLS_setup?: Promise<{ +}, __VLS_expose?: (exposed: {}) => void, __VLS_setup?: Promise<{ props: { - a?: T; - b?: T; c?: T; d: T; - }; + a?: T; + b?: T; + } & import(\\"vue\\").VNodeProps & import(\\"vue\\").AllowedComponentProps & import(\\"vue\\").ComponentCustomProps; expose(exposed: {}): void; attrs: any; slots: {}; @@ -320,11 +310,11 @@ exports[`vue-tsc-dts > Input: defineProp_B/script-setup-generic.vue, Output: def }> & { __ctx?: { props: { - a?: T; - b?: T; c?: T; d: T; - }; + a?: T; + b?: T; + } & import(\\"vue\\").VNodeProps & import(\\"vue\\").AllowedComponentProps & import(\\"vue\\").ComponentCustomProps; expose(exposed: {}): void; attrs: any; slots: {}; @@ -347,6 +337,38 @@ export default _default; " `; +exports[`vue-tsc-dts > Input: generic-interface/main.vue, Output: generic-interface/main.vue.d.ts 1`] = ` +"declare const _default: (__VLS_props: { + foo: T; +} & import(\\"vue\\").VNodeProps & import(\\"vue\\").AllowedComponentProps & import(\\"vue\\").ComponentCustomProps, __VLS_ctx?: { + slots: {}; + attrs: any; + emit: any; +}, __VLS_expose?: (exposed: {}) => void, __VLS_setup?: Promise<{ + props: { + foo: T; + } & import(\\"vue\\").VNodeProps & import(\\"vue\\").AllowedComponentProps & import(\\"vue\\").ComponentCustomProps; + expose(exposed: {}): void; + attrs: any; + slots: {}; + emit: any; +}>) => import(\\"vue\\").VNode & { + __ctx?: { + props: { + foo: T; + } & import(\\"vue\\").VNodeProps & import(\\"vue\\").AllowedComponentProps & import(\\"vue\\").ComponentCustomProps; + expose(exposed: {}): void; + attrs: any; + slots: {}; + emit: any; + }; +}; +export default _default; +" +`; + exports[`vue-tsc-dts > Input: slots/main.vue, Output: slots/main.vue.d.ts 1`] = ` "declare const _default: __VLS_WithTemplateSlots>, {}, {}>, Partial