diff --git a/packages/runtime-core/__tests__/apiCreateComponent.spec.tsx b/packages/runtime-core/__tests__/apiCreateComponent.spec.tsx index f02b089f..3fd21122 100644 --- a/packages/runtime-core/__tests__/apiCreateComponent.spec.tsx +++ b/packages/runtime-core/__tests__/apiCreateComponent.spec.tsx @@ -67,7 +67,14 @@ test('createComponent type inference', () => { } }) // test TSX props inference - ; + ; }) test('type inference w/ optional props declaration', () => { diff --git a/packages/runtime-core/src/apiCreateComponent.ts b/packages/runtime-core/src/apiCreateComponent.ts index 6353f4f0..1c01cc6f 100644 --- a/packages/runtime-core/src/apiCreateComponent.ts +++ b/packages/runtime-core/src/apiCreateComponent.ts @@ -9,13 +9,31 @@ import { SetupContext, RenderFunction } from './component' import { ComponentPublicInstance } from './componentProxy' import { ExtractPropTypes } from './componentProps' import { isFunction } from '@vue/shared' +import { Ref } from '@vue/reactivity' + +interface BaseProps { + [key: string]: any + key?: string | number + ref?: string | Ref | Function +} // overload 1: direct setup function // (uses user defined props interface) +// __isConstructor: true is a type-only differentiator to avoid returned +// constructor type from being matched as an options object in h() export function createComponent( setup: (props: Props, ctx: SetupContext) => RawBindings | RenderFunction ): { - new (): ComponentPublicInstance + __isConstructor: true + new (): ComponentPublicInstance< + Props, + RawBindings, + {}, + {}, + {}, + // public props + BaseProps & Props + > } // overload 2: object format with no props @@ -30,11 +48,19 @@ export function createComponent< >( options: ComponentOptionsWithoutProps ): { - new (): ComponentPublicInstance + __isConstructor: true + new (): ComponentPublicInstance< + Props, + RawBindings, + D, + C, + M, + BaseProps & Props + > } // overload 3: object format with array props declaration -// props inferred as { [key in PropNames]?: unknown } +// props inferred as { [key in PropNames]?: any } // return type is for Vetur and TSX support export function createComponent< PropNames extends string, @@ -45,13 +71,9 @@ export function createComponent< >( options: ComponentOptionsWithArrayProps ): { - new (): ComponentPublicInstance< - { [key in PropNames]?: unknown }, - RawBindings, - D, - C, - M - > + __isConstructor: true + // array props technically doesn't place any contraints on props in TSX + new (): ComponentPublicInstance } // overload 4: object format with object props declaration @@ -65,14 +87,15 @@ export function createComponent< >( options: ComponentOptionsWithObjectProps ): { + __isConstructor: true // for Vetur and TSX support new (): ComponentPublicInstance< - ExtractPropTypes, + ExtractPropTypes, RawBindings, D, C, M, - ExtractPropTypes + BaseProps & ExtractPropTypes > } diff --git a/packages/runtime-core/src/apiOptions.ts b/packages/runtime-core/src/apiOptions.ts index 4054e3d3..7f764ddc 100644 --- a/packages/runtime-core/src/apiOptions.ts +++ b/packages/runtime-core/src/apiOptions.ts @@ -65,6 +65,10 @@ export interface ComponentOptionsBase< components?: Record directives?: Record inheritAttrs?: boolean + + // type-only differentiator to separate OptionWihtoutProps from a constructor + // type returned by createComponent() + __isConstructor?: never } export type ComponentOptionsWithoutProps< diff --git a/packages/runtime-core/src/h.ts b/packages/runtime-core/src/h.ts index b7a9ff49..f0ff4ed5 100644 --- a/packages/runtime-core/src/h.ts +++ b/packages/runtime-core/src/h.ts @@ -133,9 +133,7 @@ export function h

( ): VNode export function h

( type: ComponentOptionsWithArrayProps

, - // TODO for now this doesn't really do anything, but it would become useful - // if we make props required by default - props?: (RawProps & { [key in P]?: any }) | null, + props?: RawProps | null, children?: RawChildren | RawSlots ): VNode export function h

(