diff --git a/packages/runtime-core/__tests__/components/Suspense.spec.ts b/packages/runtime-core/__tests__/components/Suspense.spec.ts index 5b71689a..cb8ece48 100644 --- a/packages/runtime-core/__tests__/components/Suspense.spec.ts +++ b/packages/runtime-core/__tests__/components/Suspense.spec.ts @@ -11,7 +11,8 @@ import { watch, watchEffect, onUnmounted, - onErrorCaptured + onErrorCaptured, + Component } from '@vue/runtime-test' describe('Suspense', () => { @@ -30,7 +31,7 @@ describe('Suspense', () => { setup(props: any, { slots }: any) { const p = new Promise(resolve => { setTimeout(() => { - resolve(() => h(comp, props, slots)) + resolve(() => h(comp, props, slots)) }, delay) }) // in Node 12, due to timer/nextTick mechanism change, we have to wait diff --git a/packages/runtime-core/src/apiDefineComponent.ts b/packages/runtime-core/src/apiDefineComponent.ts index 083f0dd6..c235e30c 100644 --- a/packages/runtime-core/src/apiDefineComponent.ts +++ b/packages/runtime-core/src/apiDefineComponent.ts @@ -5,7 +5,7 @@ import { ComponentOptionsWithArrayProps, ComponentOptionsWithObjectProps } from './componentOptions' -import { SetupContext, RenderFunction } from './component' +import { SetupContext, RenderFunction, FunctionalComponent } from './component' import { ComponentPublicInstance } from './componentProxy' import { ExtractPropTypes, ComponentPropsOptions } from './componentProps' import { EmitsOptions } from './componentEmits' @@ -34,7 +34,7 @@ export function defineComponent( // public props VNodeProps & Props > -} +} & FunctionalComponent // overload 2: object format with no props // (uses user defined props interface) @@ -59,7 +59,7 @@ export function defineComponent< E, VNodeProps & Props > -} +} & ComponentOptionsWithoutProps // overload 3: object format with array props declaration // props inferred as { [key in PropNames]?: any } @@ -85,7 +85,7 @@ export function defineComponent< ): { // array props technically doesn't place any contraints on props in TSX new (): ComponentPublicInstance -} +} & ComponentOptionsWithArrayProps // overload 4: object format with object props declaration // see `ExtractPropTypes` in ./componentProps.ts @@ -119,7 +119,7 @@ export function defineComponent< E, VNodeProps & ExtractPropTypes > -} +} & ComponentOptionsWithObjectProps // implementation, close to no-op export function defineComponent(options: unknown) { diff --git a/packages/runtime-core/src/h.ts b/packages/runtime-core/src/h.ts index 099fe380..aebd8506 100644 --- a/packages/runtime-core/src/h.ts +++ b/packages/runtime-core/src/h.ts @@ -67,6 +67,11 @@ interface Constructor

{ new (): { $props: P } } +// Excludes Component type from returned `defineComponent` +type NotDefinedComponent = T extends Constructor + ? never + : T + // The following is a series of overloads for providing props validation of // manually written render functions. @@ -110,8 +115,10 @@ export function h

( // catch-all for generic component types export function h(type: Component, children?: RawChildren): VNode -export function h( - type: ComponentOptions | FunctionalComponent<{}>, + +// exclude `defineComponent` +export function h>( + type: NotDefinedComponent, props?: RawProps | null, children?: RawChildren | RawSlots ): VNode diff --git a/test-dts/h.test-d.ts b/test-dts/h.test-d.ts index 338e1fc3..88b1a025 100644 --- a/test-dts/h.test-d.ts +++ b/test-dts/h.test-d.ts @@ -1,4 +1,4 @@ -import { expectError } from 'tsd' +import { expectError, expectAssignable } from 'tsd' import { describe, h, @@ -131,3 +131,34 @@ describe('h support for generic component type', () => { } foo({}) }) + +// #993 +describe('describeComponent extends Component', () => { + // functional + expectAssignable( + defineComponent((_props: { foo?: string; bar: number }) => {}) + ) + + // typed props + expectAssignable(defineComponent({})) + + // prop arrays + expectAssignable( + defineComponent({ + props: ['a', 'b'] + }) + ) + + // prop object + expectAssignable( + defineComponent({ + props: { + foo: String, + bar: { + type: Number, + required: true + } + } + }) + ) +})