diff --git a/packages/component-meta/lib/base.ts b/packages/component-meta/lib/base.ts index 3486005cf..0f181f67b 100644 --- a/packages/component-meta/lib/base.ts +++ b/packages/component-meta/lib/base.ts @@ -537,7 +537,7 @@ function createSchemaResolvers( const propType = typeChecker.getNonNullableType(typeChecker.getTypeOfSymbolAtLocation(prop, symbolNode)); const signatures = propType.getCallSignatures(); const paramType = signatures[0].parameters[0]; - const subtype = typeChecker.getTypeOfSymbolAtLocation(paramType, symbolNode); + const subtype = paramType ? typeChecker.getTypeOfSymbolAtLocation(paramType, symbolNode) : typeChecker.getAnyType(); let schema: PropertyMetaSchema; let declarations: Declaration[]; diff --git a/packages/component-meta/tests/index.spec.ts b/packages/component-meta/tests/index.spec.ts index c0841125a..65659039a 100644 --- a/packages/component-meta/tests/index.spec.ts +++ b/packages/component-meta/tests/index.spec.ts @@ -594,6 +594,34 @@ const worker = (checker: ComponentMetaChecker, withTsconfig: boolean) => describ expect(d).toBeDefined(); }); + test('defineSlots', () => { + const componentPath = path.resolve(__dirname, '../../../test-workspace/component-meta/template-slots/component-define-slots.vue'); + const meta = checker.getComponentMeta(componentPath); + + expect(meta.type).toEqual(TypeMeta.Class); + + const a = meta.slots.find(slot => + slot.name === 'default' + && slot.type === '{ num: number; }' + ); + const b = meta.slots.find(slot => + slot.name === 'named-slot' + && slot.type === '{ str: string; }' + ); + const c = meta.slots.find(slot => + slot.name === 'vbind' + && slot.type === '{ num: number; str: string; }' + ); + const d = meta.slots.find(slot => + slot.name === 'no-bind' + ); + + expect(a).toBeDefined(); + expect(b).toBeDefined(); + expect(c).toBeDefined(); + expect(d).toBeDefined(); + }); + test('template-slots for generic', () => { const componentPath = path.resolve(__dirname, '../../../test-workspace/component-meta/generic/component.vue'); const meta = checker.getComponentMeta(componentPath); diff --git a/packages/tsc/tests/__snapshots__/dts.spec.ts.snap b/packages/tsc/tests/__snapshots__/dts.spec.ts.snap index 3c3d92da7..38491bd2e 100644 --- a/packages/tsc/tests/__snapshots__/dts.spec.ts.snap +++ b/packages/tsc/tests/__snapshots__/dts.spec.ts.snap @@ -561,6 +561,58 @@ type __VLS_WithTemplateSlots = T & { " `; +exports[`vue-tsc-dts > Input: template-slots/component-define-slots.vue, Output: template-slots/component-define-slots.vue.d.ts 1`] = ` +"import { VNode } from 'vue'; +declare const _default: __VLS_WithTemplateSlots>, {}, {}>, Readonly<{ + default: (props: { + num: number; + }) => VNode[]; + 'named-slot': (props: { + str: string; + }) => VNode[]; + vbind: (props: { + num: number; + str: string; + }) => VNode[]; + 'no-bind': () => VNode[]; +}> & { + default: (props: { + num: number; + }) => VNode[]; + 'named-slot': (props: { + str: string; + }) => VNode[]; + vbind: (props: { + num: number; + str: string; + }) => VNode[]; + 'no-bind': () => VNode[]; +}>; +export default _default; +type __VLS_WithTemplateSlots = T & { + new (): { + $slots: S; + }; +}; +" +`; + exports[`vue-tsc-dts > Input: template-slots/component-no-script.vue, Output: template-slots/component-no-script.vue.d.ts 1`] = ` "declare const _default: __VLS_WithTemplateSlots>, {}, {}>, { "no-bind"?(_: {}): any; diff --git a/test-workspace/component-meta/template-slots/component-define-slots.vue b/test-workspace/component-meta/template-slots/component-define-slots.vue new file mode 100644 index 000000000..9d1172171 --- /dev/null +++ b/test-workspace/component-meta/template-slots/component-define-slots.vue @@ -0,0 +1,14 @@ + + +