diff --git a/packages/runtime-core/src/apiOptions.ts b/packages/runtime-core/src/apiOptions.ts index 472462cf..7ed2590a 100644 --- a/packages/runtime-core/src/apiOptions.ts +++ b/packages/runtime-core/src/apiOptions.ts @@ -16,7 +16,7 @@ import { camelize } from '@vue/shared' import { computed, ComputedOptions } from './apiReactivity' -import { watch } from './apiWatch' +import { watch, WatchOptions } from './apiWatch' import { provide, inject } from './apiInject' import { onBeforeMount, @@ -45,16 +45,14 @@ export interface LegacyOptions { // TODO watch array watch?: Record< string, - | string - | Function - | { handler: Function; deep?: boolean; immediate: boolean } + string | Function | { handler: Function } & WatchOptions > provide?: Data | (() => Data) inject?: | string[] | Record< string | symbol, - string | symbol | { from: string | symbol; default: any } + string | symbol | { from: string | symbol; default?: any } > // composition diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index c3ac0b52..afd9a98a 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -58,12 +58,12 @@ interface ComponentOptionsBase extends LegacyOptions { directives?: Record } -interface ComponentOptionsWithoutProps +export interface ComponentOptionsWithoutProps extends ComponentOptionsBase { props?: undefined } -interface ComponentOptionsWithArrayProps< +export interface ComponentOptionsWithArrayProps< PropNames extends string = string, RawBindings = {}, Props = { [key in PropNames]?: unknown } @@ -71,7 +71,7 @@ interface ComponentOptionsWithArrayProps< props: PropNames[] } -interface ComponentOptionsWithProps< +export interface ComponentOptionsWithProps< PropsOptions = ComponentPropsOptions, RawBindings = {}, Props = ExtractPropTypes diff --git a/packages/runtime-core/src/h.ts b/packages/runtime-core/src/h.ts index df16598c..c2ff1bed 100644 --- a/packages/runtime-core/src/h.ts +++ b/packages/runtime-core/src/h.ts @@ -1,5 +1,22 @@ -import { VNodeTypes, VNode, createVNode } from './vnode' +import { + VNodeTypes, + VNode, + createVNode, + VNodeChildren, + Fragment, + Portal +} from './vnode' import { isObject, isArray } from '@vue/shared' +import { Ref } from '@vue/reactivity' +import { RawSlots } from './componentSlots' +import { + FunctionalComponent, + ComponentOptions, + ComponentOptionsWithoutProps, + ComponentOptionsWithArrayProps, + ComponentOptionsWithProps +} from './component' +import { ExtractPropTypes } from './componentProps' // `h` is a more user-friendly version of `createVNode` that allows omitting the // props when possible. It is intended for manually written render functions. @@ -30,6 +47,87 @@ h('div', {}, 'foo') // text h('div', null, {}) **/ +interface Props { + [key: string]: any + key?: string | number + ref?: string | Ref | Function + // used to differ from a single VNode object as children + _isVNode?: never + // used to differ from Array children + [Symbol.iterator]?: never +} + +type Children = string | number | VNodeChildren + +// fake constructor type returned from `createComponent` +interface Constructor

{ + new (): { $props: P } +} + +// The following is a series of overloads for providing props validation of +// manually written render functions. + +// element +export function h(type: string, children?: Children): VNode +export function h( + type: string, + props?: Props | null, + children?: Children +): VNode + +// keyed fragment +export function h(type: typeof Fragment, children?: Children): VNode +export function h( + type: typeof Fragment, + props?: (Props & { key?: string | number }) | null, + children?: Children +): VNode + +// portal +export function h(type: typeof Portal, children?: Children): VNode +export function h( + type: typeof Portal, + props?: (Props & { target: any }) | null, + children?: Children +): VNode + +// functional component +export function h(type: FunctionalComponent, children?: Children): VNode +export function h

( + type: FunctionalComponent

, + props?: (Props & P) | null, + children?: Children | RawSlots +): VNode + +// stateful component +export function h(type: ComponentOptions, children?: Children): VNode +export function h

( + type: ComponentOptionsWithoutProps

, + props?: (Props & P) | null, + children?: Children | RawSlots +): 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?: (Props & { [key in P]?: any }) | null, + children?: Children | RawSlots +): VNode +export function h

( + type: ComponentOptionsWithProps

, + props?: (Props & ExtractPropTypes

) | null, + children?: Children | RawSlots +): VNode + +// fake constructor type returned by `createComponent` +export function h(type: Constructor, children?: Children): VNode +export function h

( + type: Constructor

, + props?: (Props & P) | null, + children?: Children | RawSlots +): VNode + +// Actual implementation export function h( type: VNodeTypes, propsOrChildren?: any, diff --git a/packages/runtime-core/src/vnode.ts b/packages/runtime-core/src/vnode.ts index 35810645..57b5b141 100644 --- a/packages/runtime-core/src/vnode.ts +++ b/packages/runtime-core/src/vnode.ts @@ -24,6 +24,7 @@ export type VNodeTypes = | Function | Object | typeof Fragment + | typeof Portal | typeof Text | typeof Empty