types(runtime-core): refactor defineComponent (#1883)
This commit is contained in:
@@ -6,22 +6,65 @@ import {
|
||||
ComponentOptionsWithObjectProps,
|
||||
ComponentOptionsMixin,
|
||||
RenderFunction,
|
||||
UnwrapAsyncBindings
|
||||
ComponentOptionsBase
|
||||
} from './componentOptions'
|
||||
import {
|
||||
SetupContext,
|
||||
FunctionalComponent,
|
||||
AllowedComponentProps,
|
||||
ComponentCustomProps
|
||||
} from './component'
|
||||
import {
|
||||
CreateComponentPublicInstance,
|
||||
ComponentPublicInstanceConstructor
|
||||
} from './componentPublicInstance'
|
||||
import { ExtractPropTypes, ComponentPropsOptions } from './componentProps'
|
||||
import { EmitsOptions } from './componentEmits'
|
||||
import { isFunction } from '@vue/shared'
|
||||
import { VNodeProps } from './vnode'
|
||||
import {
|
||||
CreateComponentPublicInstance,
|
||||
ComponentPublicInstanceConstructor
|
||||
} from './componentPublicInstance'
|
||||
|
||||
export type PublicProps = VNodeProps &
|
||||
AllowedComponentProps &
|
||||
ComponentCustomProps
|
||||
|
||||
export type DefineComponent<
|
||||
PropsOrPropOptions = any,
|
||||
RawBindings = any,
|
||||
D = any,
|
||||
C extends ComputedOptions = ComputedOptions,
|
||||
M extends MethodOptions = MethodOptions,
|
||||
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||
E extends EmitsOptions = Record<string, any>,
|
||||
EE extends string = string,
|
||||
PP = PublicProps,
|
||||
RequiredProps = Readonly<ExtractPropTypes<PropsOrPropOptions>>,
|
||||
OptionalProps = Readonly<ExtractPropTypes<PropsOrPropOptions, false>>
|
||||
> = ComponentPublicInstanceConstructor<
|
||||
CreateComponentPublicInstance<
|
||||
OptionalProps,
|
||||
RawBindings,
|
||||
D,
|
||||
C,
|
||||
M,
|
||||
Mixin,
|
||||
Extends,
|
||||
E,
|
||||
PP & OptionalProps
|
||||
> &
|
||||
RequiredProps
|
||||
> &
|
||||
ComponentOptionsBase<
|
||||
RequiredProps,
|
||||
RawBindings,
|
||||
D,
|
||||
C,
|
||||
M,
|
||||
Mixin,
|
||||
Extends,
|
||||
E,
|
||||
EE
|
||||
> &
|
||||
PP
|
||||
|
||||
// defineComponent is a utility that is primarily used for type inference
|
||||
// when declaring components. Type inference is provided in the component
|
||||
@@ -35,21 +78,7 @@ export function defineComponent<Props, RawBindings = object>(
|
||||
props: Readonly<Props>,
|
||||
ctx: SetupContext
|
||||
) => RawBindings | RenderFunction
|
||||
): ComponentPublicInstanceConstructor<
|
||||
CreateComponentPublicInstance<
|
||||
Props,
|
||||
UnwrapAsyncBindings<RawBindings>,
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
// public props
|
||||
VNodeProps & Props & AllowedComponentProps & ComponentCustomProps
|
||||
>
|
||||
> &
|
||||
FunctionalComponent<Props>
|
||||
): DefineComponent<Props, RawBindings>
|
||||
|
||||
// overload 2: object format with no props
|
||||
// (uses user defined props interface)
|
||||
@@ -58,11 +87,11 @@ export function defineComponent<
|
||||
Props = {},
|
||||
RawBindings = {},
|
||||
D = {},
|
||||
C extends ComputedOptions = {},
|
||||
M extends MethodOptions = {},
|
||||
C extends ComputedOptions = ComputedOptions,
|
||||
M extends MethodOptions = MethodOptions,
|
||||
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||
E extends EmitsOptions = Record<string, any>,
|
||||
E extends EmitsOptions = EmitsOptions,
|
||||
EE extends string = string
|
||||
>(
|
||||
options: ComponentOptionsWithoutProps<
|
||||
@@ -76,30 +105,7 @@ export function defineComponent<
|
||||
E,
|
||||
EE
|
||||
>
|
||||
): ComponentPublicInstanceConstructor<
|
||||
CreateComponentPublicInstance<
|
||||
Props,
|
||||
UnwrapAsyncBindings<RawBindings>,
|
||||
D,
|
||||
C,
|
||||
M,
|
||||
Mixin,
|
||||
Extends,
|
||||
E,
|
||||
VNodeProps & Props & AllowedComponentProps & ComponentCustomProps
|
||||
>
|
||||
> &
|
||||
ComponentOptionsWithoutProps<
|
||||
Props,
|
||||
RawBindings,
|
||||
D,
|
||||
C,
|
||||
M,
|
||||
Mixin,
|
||||
Extends,
|
||||
E,
|
||||
EE
|
||||
>
|
||||
): DefineComponent<Props, RawBindings, D, C, M, Mixin, Extends, E, EE>
|
||||
|
||||
// overload 3: object format with array props declaration
|
||||
// props inferred as { [key in PropNames]?: any }
|
||||
@@ -126,32 +132,17 @@ export function defineComponent<
|
||||
E,
|
||||
EE
|
||||
>
|
||||
): ComponentPublicInstanceConstructor<
|
||||
// array props technically doesn't place any constraints on props in TSX before,
|
||||
// but now we can export array props in TSX
|
||||
CreateComponentPublicInstance<
|
||||
Readonly<{ [key in PropNames]?: any }>,
|
||||
UnwrapAsyncBindings<RawBindings>,
|
||||
D,
|
||||
C,
|
||||
M,
|
||||
Mixin,
|
||||
Extends,
|
||||
E,
|
||||
AllowedComponentProps & ComponentCustomProps
|
||||
>
|
||||
> &
|
||||
ComponentOptionsWithArrayProps<
|
||||
PropNames,
|
||||
RawBindings,
|
||||
D,
|
||||
C,
|
||||
M,
|
||||
Mixin,
|
||||
Extends,
|
||||
E,
|
||||
EE
|
||||
>
|
||||
): DefineComponent<
|
||||
Readonly<{ [key in PropNames]?: any }>,
|
||||
RawBindings,
|
||||
D,
|
||||
C,
|
||||
M,
|
||||
Mixin,
|
||||
Extends,
|
||||
E,
|
||||
EE
|
||||
>
|
||||
|
||||
// overload 4: object format with object props declaration
|
||||
// see `ExtractPropTypes` in ./componentProps.ts
|
||||
@@ -179,33 +170,20 @@ export function defineComponent<
|
||||
E,
|
||||
EE
|
||||
>
|
||||
): ComponentPublicInstanceConstructor<
|
||||
CreateComponentPublicInstance<
|
||||
ExtractPropTypes<PropsOptions, false>,
|
||||
UnwrapAsyncBindings<RawBindings>,
|
||||
D,
|
||||
C,
|
||||
M,
|
||||
Mixin,
|
||||
Extends,
|
||||
E,
|
||||
VNodeProps & AllowedComponentProps & ComponentCustomProps
|
||||
> &
|
||||
Readonly<ExtractPropTypes<PropsOptions>>
|
||||
> &
|
||||
ComponentOptionsWithObjectProps<
|
||||
PropsOptions,
|
||||
RawBindings,
|
||||
D,
|
||||
C,
|
||||
M,
|
||||
Mixin,
|
||||
Extends,
|
||||
E,
|
||||
EE
|
||||
>
|
||||
): DefineComponent<PropsOptions, RawBindings, D, C, M, Mixin, Extends, E, EE>
|
||||
|
||||
// implementation, close to no-op
|
||||
export function defineComponent(options: unknown) {
|
||||
return isFunction(options) ? { setup: options, name: options.name } : options
|
||||
}
|
||||
|
||||
defineComponent({
|
||||
async setup() {
|
||||
return {
|
||||
a: 123
|
||||
}
|
||||
},
|
||||
render() {
|
||||
this.a
|
||||
}
|
||||
})
|
||||
|
||||
@@ -26,7 +26,12 @@ import { warn } from './warning'
|
||||
import { ErrorCodes, callWithErrorHandling } from './errorHandling'
|
||||
import { AppContext, createAppContext, AppConfig } from './apiCreateApp'
|
||||
import { Directive, validateDirectiveName } from './directives'
|
||||
import { applyOptions, ComponentOptions } from './componentOptions'
|
||||
import {
|
||||
applyOptions,
|
||||
ComponentOptions,
|
||||
ComputedOptions,
|
||||
MethodOptions
|
||||
} from './componentOptions'
|
||||
import {
|
||||
EmitsOptions,
|
||||
ObjectEmitsOptions,
|
||||
@@ -118,13 +123,29 @@ export interface ClassComponent {
|
||||
* values, e.g. checking if its a function or not. This is mostly for internal
|
||||
* implementation code.
|
||||
*/
|
||||
export type ConcreteComponent = ComponentOptions | FunctionalComponent<any, any>
|
||||
export type ConcreteComponent<
|
||||
Props = {},
|
||||
RawBindings = any,
|
||||
D = any,
|
||||
C extends ComputedOptions = ComputedOptions,
|
||||
M extends MethodOptions = MethodOptions
|
||||
> =
|
||||
| ComponentOptions<Props, RawBindings, D, C, M>
|
||||
| FunctionalComponent<Props, any>
|
||||
|
||||
/**
|
||||
* A type used in public APIs where a component type is expected.
|
||||
* The constructor type is an artificial type returned by defineComponent().
|
||||
*/
|
||||
export type Component = ConcreteComponent | ComponentPublicInstanceConstructor
|
||||
export type Component<
|
||||
Props = any,
|
||||
RawBindings = any,
|
||||
D = any,
|
||||
C extends ComputedOptions = ComputedOptions,
|
||||
M extends MethodOptions = MethodOptions
|
||||
> =
|
||||
| ConcreteComponent<Props, RawBindings, D, C, M>
|
||||
| ComponentPublicInstanceConstructor<Props>
|
||||
|
||||
export { ComponentOptions }
|
||||
|
||||
|
||||
@@ -72,8 +72,6 @@ export interface ComponentCustomOptions {}
|
||||
|
||||
export type RenderFunction = () => VNodeChild
|
||||
|
||||
export type UnwrapAsyncBindings<T> = T extends Promise<infer S> ? S : T
|
||||
|
||||
export interface ComponentOptionsBase<
|
||||
Props,
|
||||
RawBindings,
|
||||
@@ -92,7 +90,7 @@ export interface ComponentOptionsBase<
|
||||
this: void,
|
||||
props: Props,
|
||||
ctx: SetupContext<E>
|
||||
) => RawBindings | RenderFunction | void
|
||||
) => Promise<RawBindings> | RawBindings | RenderFunction | void
|
||||
name?: string
|
||||
template?: string | object // can be a direct DOM node
|
||||
// Note: we are intentionally using the signature-less `Function` type here
|
||||
@@ -230,10 +228,29 @@ export type ComponentOptionsWithObjectProps<
|
||||
>
|
||||
>
|
||||
|
||||
export type ComponentOptions =
|
||||
| ComponentOptionsWithoutProps<any, any, any, any, any>
|
||||
| ComponentOptionsWithObjectProps<any, any, any, any, any>
|
||||
| ComponentOptionsWithArrayProps<any, any, any, any, any>
|
||||
export type ComponentOptions<
|
||||
Props = {},
|
||||
RawBindings = any,
|
||||
D = any,
|
||||
C extends ComputedOptions = any,
|
||||
M extends MethodOptions = any,
|
||||
Mixin extends ComponentOptionsMixin = any,
|
||||
Extends extends ComponentOptionsMixin = any,
|
||||
E extends EmitsOptions = any
|
||||
> = ComponentOptionsBase<Props, RawBindings, D, C, M, Mixin, Extends, E> &
|
||||
ThisType<
|
||||
CreateComponentPublicInstance<
|
||||
{},
|
||||
RawBindings,
|
||||
D,
|
||||
C,
|
||||
M,
|
||||
Mixin,
|
||||
Extends,
|
||||
E,
|
||||
Readonly<Props>
|
||||
>
|
||||
>
|
||||
|
||||
export type ComponentOptionsMixin = ComponentOptionsBase<
|
||||
any,
|
||||
@@ -638,17 +655,13 @@ export function applyOptions(
|
||||
onRenderTriggered(renderTriggered.bind(publicThis))
|
||||
}
|
||||
if (__DEV__ && beforeDestroy) {
|
||||
warn(
|
||||
`\`beforeDestroy\` has been renamed to \`beforeUnmount\`.`
|
||||
)
|
||||
warn(`\`beforeDestroy\` has been renamed to \`beforeUnmount\`.`)
|
||||
}
|
||||
if (beforeUnmount) {
|
||||
onBeforeUnmount(beforeUnmount.bind(publicThis))
|
||||
}
|
||||
if (__DEV__ && destroyed) {
|
||||
warn(
|
||||
`\`destroyed\` has been renamed to \`unmounted\`.`
|
||||
)
|
||||
warn(`\`destroyed\` has been renamed to \`unmounted\`.`)
|
||||
}
|
||||
if (unmounted) {
|
||||
onUnmounted(unmounted.bind(publicThis))
|
||||
|
||||
@@ -27,8 +27,7 @@ import {
|
||||
OptionTypesType,
|
||||
OptionTypesKeys,
|
||||
resolveMergedOptions,
|
||||
isInBeforeCreate,
|
||||
UnwrapAsyncBindings
|
||||
isInBeforeCreate
|
||||
} from './componentOptions'
|
||||
import { EmitsOptions, EmitFn } from './componentEmits'
|
||||
import { Slots } from './componentSlots'
|
||||
@@ -102,7 +101,18 @@ type UnwrapMixinsType<
|
||||
type EnsureNonVoid<T> = T extends void ? {} : T
|
||||
|
||||
export type ComponentPublicInstanceConstructor<
|
||||
T extends ComponentPublicInstance = ComponentPublicInstance<any>
|
||||
T extends ComponentPublicInstance<
|
||||
Props,
|
||||
RawBindings,
|
||||
D,
|
||||
C,
|
||||
M
|
||||
> = ComponentPublicInstance<any>,
|
||||
Props = any,
|
||||
RawBindings = any,
|
||||
D = any,
|
||||
C extends ComputedOptions = ComputedOptions,
|
||||
M extends MethodOptions = MethodOptions
|
||||
> = {
|
||||
__isFragment?: never
|
||||
__isTeleport?: never
|
||||
@@ -138,6 +148,7 @@ export type CreateComponentPublicInstance<
|
||||
PublicProps,
|
||||
ComponentOptionsBase<P, B, D, C, M, Mixin, Extends, E>
|
||||
>
|
||||
|
||||
// public properties exposed on the proxy, which is used as the render context
|
||||
// in templates (as `this` in the render option)
|
||||
export type ComponentPublicInstance<
|
||||
@@ -169,7 +180,7 @@ export type ComponentPublicInstance<
|
||||
options?: WatchOptions
|
||||
): WatchStopHandle
|
||||
} & P &
|
||||
ShallowUnwrapRef<UnwrapAsyncBindings<B>> &
|
||||
ShallowUnwrapRef<B> &
|
||||
D &
|
||||
ExtractComputedReturns<C> &
|
||||
M &
|
||||
|
||||
@@ -10,9 +10,9 @@ import { Teleport, TeleportProps } from './components/Teleport'
|
||||
import { Suspense, SuspenseProps } from './components/Suspense'
|
||||
import { isObject, isArray } from '@vue/shared'
|
||||
import { RawSlots } from './componentSlots'
|
||||
import { FunctionalComponent, Component } from './component'
|
||||
import { ComponentOptions } from './componentOptions'
|
||||
import { FunctionalComponent, Component, ComponentOptions } from './component'
|
||||
import { EmitsOptions } from './componentEmits'
|
||||
import { DefineComponent } from './apiDefineComponent'
|
||||
|
||||
// `h` is a more user-friendly version of `createVNode` that allows omitting the
|
||||
// props when possible. It is intended for manually written render functions.
|
||||
@@ -50,7 +50,7 @@ type RawProps = VNodeProps & {
|
||||
__v_isVNode?: never
|
||||
// used to differ from Array children
|
||||
[Symbol.iterator]?: never
|
||||
} & { [key: string]: any }
|
||||
} & Record<string, any>
|
||||
|
||||
type RawChildren =
|
||||
| string
|
||||
@@ -112,10 +112,17 @@ export function h<P, E extends EmitsOptions = {}>(
|
||||
// catch-all for generic component types
|
||||
export function h(type: Component, children?: RawChildren): VNode
|
||||
|
||||
// component without props
|
||||
export function h(
|
||||
type: Component,
|
||||
props: null,
|
||||
children?: RawChildren | RawSlots
|
||||
): VNode
|
||||
|
||||
// exclude `defineComponent` constructors
|
||||
export function h<T extends ComponentOptions | FunctionalComponent<{}>>(
|
||||
type: T,
|
||||
props?: RawProps | null,
|
||||
export function h<P>(
|
||||
type: ComponentOptions<P>,
|
||||
props?: (RawProps & P) | ({} extends P ? null : never),
|
||||
children?: RawChildren | RawSlots
|
||||
): VNode
|
||||
|
||||
@@ -127,6 +134,14 @@ export function h<P>(
|
||||
children?: RawChildren | RawSlots
|
||||
): VNode
|
||||
|
||||
// fake constructor type returned by `defineComponent`
|
||||
export function h(type: DefineComponent, children?: RawChildren): VNode
|
||||
export function h<P>(
|
||||
type: DefineComponent<P>,
|
||||
props?: (RawProps & P) | ({} extends P ? null : never),
|
||||
children?: RawChildren | RawSlots
|
||||
): VNode
|
||||
|
||||
// Actual implementation
|
||||
export function h(type: any, propsOrChildren?: any, children?: any): VNode {
|
||||
const l = arguments.length
|
||||
|
||||
@@ -41,7 +41,7 @@ export {
|
||||
} from './apiLifecycle'
|
||||
export { provide, inject } from './apiInject'
|
||||
export { nextTick } from './scheduler'
|
||||
export { defineComponent } from './apiDefineComponent'
|
||||
export { defineComponent, DefineComponent } from './apiDefineComponent'
|
||||
export { defineAsyncComponent } from './apiAsyncComponent'
|
||||
|
||||
// Advanced API ----------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user