From 5b1cf1f1e4a7ca8e294da6d1afc6fb74f1356858 Mon Sep 17 00:00:00 2001 From: KazariEX <1364035137@qq.com> Date: Sat, 5 Oct 2024 13:51:16 +0800 Subject: [PATCH 1/4] fix: infer union props to options correctly --- .../language-core/lib/codegen/globalTypes.ts | 19 ++++++++++++++++ .../language-core/lib/codegen/localTypes.ts | 22 ++++++------------- .../passedFixtures/vue3/core#12110/comp.vue | 16 ++++++++++++++ .../passedFixtures/vue3/core#12110/main.vue | 9 ++++++++ 4 files changed, 51 insertions(+), 15 deletions(-) create mode 100644 test-workspace/tsc/passedFixtures/vue3/core#12110/comp.vue create mode 100644 test-workspace/tsc/passedFixtures/vue3/core#12110/main.vue diff --git a/packages/language-core/lib/codegen/globalTypes.ts b/packages/language-core/lib/codegen/globalTypes.ts index 1f7c027f01..cc62ee729f 100644 --- a/packages/language-core/lib/codegen/globalTypes.ts +++ b/packages/language-core/lib/codegen/globalTypes.ts @@ -87,6 +87,25 @@ export function generateGlobalTypes(lib: string, target: number, strictTemplates '__ctx' extends keyof __VLS_PickNotAny ? K extends { __ctx?: infer Ctx } ? Ctx : never : any , T extends (props: any, ctx: infer Ctx) => any ? Ctx : any >>; + type __VLS_InferUnionType = K extends keyof T ? T[K] : K extends keyof U ? U[K] : never; + type __VLS_UnionKeys = T extends any ? keyof T : never; + type __VLS_UnionRequiredKeys> = Exclude>; + type __VLS_UnionOptionalKeys> = T extends any + ? K extends keyof T + ? {} extends Pick + ? K + : never + : never + : never; + type __VLS_MergeUnion = T extends any + ? { [V in __VLS_UnionRequiredKeys]: __VLS_InferUnionType } + & { [V in __VLS_UnionOptionalKeys]?: __VLS_InferUnionType } + : never; + type __VLS_PrettifyUnion = { + [K in __VLS_UnionRequiredKeys]: T[K] + } & { + [K in __VLS_UnionOptionalKeys]?: T[K] + }; function __VLS_getVForSourceType(source: number): [number, number, number][]; function __VLS_getVForSourceType(source: string): [string, number, number][]; diff --git a/packages/language-core/lib/codegen/localTypes.ts b/packages/language-core/lib/codegen/localTypes.ts index d4939c3bf6..ce70e4689a 100644 --- a/packages/language-core/lib/codegen/localTypes.ts +++ b/packages/language-core/lib/codegen/localTypes.ts @@ -59,21 +59,13 @@ type __VLS_PropsChildren = { ); const TypePropsToOption = defineHelper( `__VLS_TypePropsToOption`, - () => compilerOptions.exactOptionalPropertyTypes ? - ` -type __VLS_TypePropsToOption = { - [K in keyof T]-?: {} extends Pick - ? { type: import('${vueCompilerOptions.lib}').PropType } - : { type: import('${vueCompilerOptions.lib}').PropType, required: true } -}; -`.trimStart() : - ` -type __VLS_NonUndefinedable = T extends undefined ? never : T; -type __VLS_TypePropsToOption = { - [K in keyof T]-?: {} extends Pick - ? { type: import('${vueCompilerOptions.lib}').PropType<__VLS_NonUndefinedable> } - : { type: import('${vueCompilerOptions.lib}').PropType, required: true } -}; + () => (compilerOptions.exactOptionalPropertyTypes ? 'type __VLS_NonUndefinedable = T extends undefined ? never : T;' : '') + ` +type __VLS_TypePropsToOption = __VLS_PrettifyUnion<__VLS_MergeUnion> extends infer U ? { + [K in keyof U]-?: { + type: import('${vueCompilerOptions.lib}').PropType<${compilerOptions.exactOptionalPropertyTypes ? '__VLS_NonUndefinedable' : 'U[K]'}>, + required: {} extends Pick ? false : true + } +} : never; `.trimStart() ); const OmitIndexSignature = defineHelper( diff --git a/test-workspace/tsc/passedFixtures/vue3/core#12110/comp.vue b/test-workspace/tsc/passedFixtures/vue3/core#12110/comp.vue new file mode 100644 index 0000000000..0d6309d91a --- /dev/null +++ b/test-workspace/tsc/passedFixtures/vue3/core#12110/comp.vue @@ -0,0 +1,16 @@ + diff --git a/test-workspace/tsc/passedFixtures/vue3/core#12110/main.vue b/test-workspace/tsc/passedFixtures/vue3/core#12110/main.vue new file mode 100644 index 0000000000..396c6e5950 --- /dev/null +++ b/test-workspace/tsc/passedFixtures/vue3/core#12110/main.vue @@ -0,0 +1,9 @@ + + + From 33628a15999268b3b9bd2265fcfca1d8ae9d7b3e Mon Sep 17 00:00:00 2001 From: KazariEX <1364035137@qq.com> Date: Sat, 5 Oct 2024 15:18:04 +0800 Subject: [PATCH 2/4] test: fix case and update snapshot --- .../language-core/lib/codegen/globalTypes.ts | 1 + .../language-core/lib/codegen/localTypes.ts | 9 ++-- .../tsc/tests/__snapshots__/dts.spec.ts.snap | 44 +++++++------------ .../tsc/passedFixtures/vue2/tsconfig.json | 1 + .../tsc/passedFixtures/vue3.4/tsconfig.json | 1 + 5 files changed, 24 insertions(+), 32 deletions(-) diff --git a/packages/language-core/lib/codegen/globalTypes.ts b/packages/language-core/lib/codegen/globalTypes.ts index cc62ee729f..a4a37e55a8 100644 --- a/packages/language-core/lib/codegen/globalTypes.ts +++ b/packages/language-core/lib/codegen/globalTypes.ts @@ -87,6 +87,7 @@ export function generateGlobalTypes(lib: string, target: number, strictTemplates '__ctx' extends keyof __VLS_PickNotAny ? K extends { __ctx?: infer Ctx } ? Ctx : never : any , T extends (props: any, ctx: infer Ctx) => any ? Ctx : any >>; + type __VLS_IsUnion = T extends U ? [U] extends [T] ? false : true : false; type __VLS_InferUnionType = K extends keyof T ? T[K] : K extends keyof U ? U[K] : never; type __VLS_UnionKeys = T extends any ? keyof T : never; type __VLS_UnionRequiredKeys> = Exclude>; diff --git a/packages/language-core/lib/codegen/localTypes.ts b/packages/language-core/lib/codegen/localTypes.ts index ce70e4689a..acab9fa2e1 100644 --- a/packages/language-core/lib/codegen/localTypes.ts +++ b/packages/language-core/lib/codegen/localTypes.ts @@ -59,13 +59,14 @@ type __VLS_PropsChildren = { ); const TypePropsToOption = defineHelper( `__VLS_TypePropsToOption`, - () => (compilerOptions.exactOptionalPropertyTypes ? 'type __VLS_NonUndefinedable = T extends undefined ? never : T;' : '') + ` -type __VLS_TypePropsToOption = __VLS_PrettifyUnion<__VLS_MergeUnion> extends infer U ? { + () => ` +${compilerOptions.exactOptionalPropertyTypes ? '' : 'type __VLS_NonUndefinedable = T extends undefined ? never : T;'} +type __VLS_TypePropsToOption extends true ? __VLS_PrettifyUnion<__VLS_MergeUnion> : T> = { [K in keyof U]-?: { - type: import('${vueCompilerOptions.lib}').PropType<${compilerOptions.exactOptionalPropertyTypes ? '__VLS_NonUndefinedable' : 'U[K]'}>, + type: import('${vueCompilerOptions.lib}').PropType<${compilerOptions.exactOptionalPropertyTypes ? 'U[K]' : '__VLS_NonUndefinedable'}>, required: {} extends Pick ? false : true } -} : never; +}; `.trimStart() ); const OmitIndexSignature = defineHelper( diff --git a/packages/tsc/tests/__snapshots__/dts.spec.ts.snap b/packages/tsc/tests/__snapshots__/dts.spec.ts.snap index 8e2099a109..9d106c0f2c 100644 --- a/packages/tsc/tests/__snapshots__/dts.spec.ts.snap +++ b/packages/tsc/tests/__snapshots__/dts.spec.ts.snap @@ -5,7 +5,7 @@ exports[`vue-tsc-dts > Input: #4577/main.vue, Output: #4577/main.vue.d.ts 1`] = value: string; }; declare const _default: (__VLS_props: NonNullable>["props"], __VLS_ctx?: __VLS_PrettifyLocal>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable>["expose"], __VLS_setup?: Promise<{ - props: __VLS_PrettifyLocal & Omit<{} & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & Readonly<{}> & Readonly<{}>, never>, never> & { + props: __VLS_PrettifyLocal & Omit<{} & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, never>, never> & { nonGeneric: string; rows: Row[]; }> & (import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps); @@ -71,9 +71,7 @@ exports[`vue-tsc-dts > Input: events/component-generic.vue, Output: events/compo "declare const _default: (__VLS_props: NonNullable>["props"], __VLS_ctx?: __VLS_PrettifyLocal>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable>["expose"], __VLS_setup?: Promise<{ props: __VLS_PrettifyLocal & Omit<{ readonly onFoo?: (value: string) => any; - } & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & Readonly<{}> & Readonly<{ - onFoo?: (value: string) => any; - }>, never>, "onFoo"> & {}> & (import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps); + } & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, never>, "onFoo"> & {}> & (import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps); expose(exposed: import("vue").ShallowUnwrapRef<{}>): void; attrs: any; slots: {}; @@ -95,10 +93,7 @@ exports[`vue-tsc-dts > Input: generic/component.vue, Output: generic/component.v props: __VLS_PrettifyLocal & Omit<{ readonly "onUpdate:title"?: (title: string) => any; readonly onBar?: (data: number) => any; - } & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & Readonly<{}> & Readonly<{ - "onUpdate:title"?: (title: string) => any; - onBar?: (data: number) => any; - }>, never>, "onUpdate:title" | "onBar"> & ({ + } & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, never>, "onUpdate:title" | "onBar"> & ({ title?: string; } & { foo: number; @@ -134,10 +129,7 @@ exports[`vue-tsc-dts > Input: generic/custom-extension-component.cext, Output: g props: __VLS_PrettifyLocal & Omit<{ readonly "onUpdate:title"?: (title: string) => any; readonly onBar?: (data: number) => any; - } & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & Readonly<{}> & Readonly<{ - "onUpdate:title"?: (title: string) => any; - onBar?: (data: number) => any; - }>, never>, "onUpdate:title" | "onBar"> & ({ + } & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, never>, "onUpdate:title" | "onBar"> & ({ title?: string; } & { foo: number; @@ -328,23 +320,21 @@ exports[`vue-tsc-dts > Input: reference-type-model/component.vue, Output: refere "qux"?: string; quxModifiers?: Record<'lazy' | 'trim', true>; }; -declare const _default: import("vue").DefineComponent>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, { +declare const _default: import("vue").DefineComponent>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, { "update:foo": (foo: number) => void; "update:bar": (bar: string[]) => void; "update:qux": (qux: string) => void; -}, string, import("vue").PublicProps, Readonly>> & Readonly<{ +}, string, import("vue").PublicProps, Readonly>> & Readonly<{ "onUpdate:foo"?: (foo: number) => any; "onUpdate:bar"?: (bar: string[]) => any; "onUpdate:qux"?: (qux: string) => any; }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; export default _default; type __VLS_NonUndefinedable = T extends undefined ? never : T; -type __VLS_TypePropsToOption = { - [K in keyof T]-?: {} extends Pick ? { - type: import('vue').PropType<__VLS_NonUndefinedable>; - } : { - type: import('vue').PropType; - required: true; +type __VLS_TypePropsToOption extends true ? __VLS_PrettifyUnion<__VLS_MergeUnion> : T> = { + [K in keyof U]-?: { + type: import('vue').PropType<__VLS_NonUndefinedable>; + required: {} extends Pick ? false : true; }; }; " @@ -352,10 +342,10 @@ type __VLS_TypePropsToOption = { exports[`vue-tsc-dts > Input: reference-type-props/component.vue, Output: reference-type-props/component.vue.d.ts 1`] = ` "import { MyProps } from './my-props'; -declare const _default: import("vue").DefineComponent, { +declare const _default: import("vue").DefineComponent, { bar: number; baz: () => string[]; -}>>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly, { +}>>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly, { bar: number; baz: () => string[]; }>>> & Readonly<{}>, { @@ -369,12 +359,10 @@ type __VLS_WithDefaults = { }> : P[K]; }; type __VLS_NonUndefinedable = T extends undefined ? never : T; -type __VLS_TypePropsToOption = { - [K in keyof T]-?: {} extends Pick ? { - type: import('vue').PropType<__VLS_NonUndefinedable>; - } : { - type: import('vue').PropType; - required: true; +type __VLS_TypePropsToOption extends true ? __VLS_PrettifyUnion<__VLS_MergeUnion> : T> = { + [K in keyof U]-?: { + type: import('vue').PropType<__VLS_NonUndefinedable>; + required: {} extends Pick ? false : true; }; }; type __VLS_PrettifyLocal = { diff --git a/test-workspace/tsc/passedFixtures/vue2/tsconfig.json b/test-workspace/tsc/passedFixtures/vue2/tsconfig.json index cc86334474..648f05fa46 100644 --- a/test-workspace/tsc/passedFixtures/vue2/tsconfig.json +++ b/test-workspace/tsc/passedFixtures/vue2/tsconfig.json @@ -26,6 +26,7 @@ "../vue3/#4649", "../vue3/#4777", "../vue3/#4820", + "../vue3/core#12110", "../vue3/components", "../vue3/defineEmits", "../vue3/defineModel", diff --git a/test-workspace/tsc/passedFixtures/vue3.4/tsconfig.json b/test-workspace/tsc/passedFixtures/vue3.4/tsconfig.json index 8a5d76fcfa..ac98bde3b2 100644 --- a/test-workspace/tsc/passedFixtures/vue3.4/tsconfig.json +++ b/test-workspace/tsc/passedFixtures/vue3.4/tsconfig.json @@ -12,6 +12,7 @@ "../vue3/#3820", "../vue3/#4777", "../vue3/#4820", + "../vue3/core#12110", "../vue3/rootEl", "../vue3/templateRef", "../vue3/templateRef_native", From 9fcac693e8df96e6f45aa10a0fdfdb473556cd7e Mon Sep 17 00:00:00 2001 From: KazariEX <1364035137@qq.com> Date: Sat, 5 Oct 2024 15:18:46 +0800 Subject: [PATCH 3/4] fix: only emit optional event --- packages/language-core/lib/codegen/template/elementEvents.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/language-core/lib/codegen/template/elementEvents.ts b/packages/language-core/lib/codegen/template/elementEvents.ts index 57f57c4c74..e22f400c3b 100644 --- a/packages/language-core/lib/codegen/template/elementEvents.ts +++ b/packages/language-core/lib/codegen/template/elementEvents.ts @@ -43,7 +43,9 @@ export function* generateElementEvents( } yield `(${newLine}`; yield `__VLS_IsFunction extends true${newLine}`; - yield `? typeof ${propsVar}${newLine}`; + yield `? {${newLine}`; + yield `${originalPropNameObjectKey}?: typeof ${propsVar}['${originalPropName}']${newLine}`; + yield `}${newLine}`; yield `: __VLS_IsFunction extends true${newLine}`; yield `? {${newLine}`; yield `/**__VLS_emit,${emitVar},${prop.arg.loc.source}*/${newLine}`; From 858cb810e628896f3955dd3b6ec7e0ff42d97e30 Mon Sep 17 00:00:00 2001 From: KazariEX <1364035137@qq.com> Date: Sat, 5 Oct 2024 15:22:11 +0800 Subject: [PATCH 4/4] test: update snapshot --- .../tsc/tests/__snapshots__/dts.spec.ts.snap | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/tsc/tests/__snapshots__/dts.spec.ts.snap b/packages/tsc/tests/__snapshots__/dts.spec.ts.snap index 9d106c0f2c..900b157b2a 100644 --- a/packages/tsc/tests/__snapshots__/dts.spec.ts.snap +++ b/packages/tsc/tests/__snapshots__/dts.spec.ts.snap @@ -5,7 +5,7 @@ exports[`vue-tsc-dts > Input: #4577/main.vue, Output: #4577/main.vue.d.ts 1`] = value: string; }; declare const _default: (__VLS_props: NonNullable>["props"], __VLS_ctx?: __VLS_PrettifyLocal>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable>["expose"], __VLS_setup?: Promise<{ - props: __VLS_PrettifyLocal & Omit<{} & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, never>, never> & { + props: __VLS_PrettifyLocal & Omit<{} & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & Readonly<{}> & Readonly<{}>, never>, never> & { nonGeneric: string; rows: Row[]; }> & (import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps); @@ -71,7 +71,9 @@ exports[`vue-tsc-dts > Input: events/component-generic.vue, Output: events/compo "declare const _default: (__VLS_props: NonNullable>["props"], __VLS_ctx?: __VLS_PrettifyLocal>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable>["expose"], __VLS_setup?: Promise<{ props: __VLS_PrettifyLocal & Omit<{ readonly onFoo?: (value: string) => any; - } & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, never>, "onFoo"> & {}> & (import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps); + } & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & Readonly<{}> & Readonly<{ + onFoo?: (value: string) => any; + }>, never>, "onFoo"> & {}> & (import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps); expose(exposed: import("vue").ShallowUnwrapRef<{}>): void; attrs: any; slots: {}; @@ -93,7 +95,10 @@ exports[`vue-tsc-dts > Input: generic/component.vue, Output: generic/component.v props: __VLS_PrettifyLocal & Omit<{ readonly "onUpdate:title"?: (title: string) => any; readonly onBar?: (data: number) => any; - } & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, never>, "onUpdate:title" | "onBar"> & ({ + } & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & Readonly<{}> & Readonly<{ + "onUpdate:title"?: (title: string) => any; + onBar?: (data: number) => any; + }>, never>, "onUpdate:title" | "onBar"> & ({ title?: string; } & { foo: number; @@ -129,7 +134,10 @@ exports[`vue-tsc-dts > Input: generic/custom-extension-component.cext, Output: g props: __VLS_PrettifyLocal & Omit<{ readonly "onUpdate:title"?: (title: string) => any; readonly onBar?: (data: number) => any; - } & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, never>, "onUpdate:title" | "onBar"> & ({ + } & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & Readonly<{}> & Readonly<{ + "onUpdate:title"?: (title: string) => any; + onBar?: (data: number) => any; + }>, never>, "onUpdate:title" | "onBar"> & ({ title?: string; } & { foo: number;