Skip to content

Commit

Permalink
types(runtime-core): refactor defineComponent (#1883)
Browse files Browse the repository at this point in the history
  • Loading branch information
pikax authored Sep 15, 2020
1 parent 848ccf5 commit 4fd468a
Show file tree
Hide file tree
Showing 8 changed files with 583 additions and 132 deletions.
12 changes: 6 additions & 6 deletions packages/reactivity/src/baseHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,17 @@ const readonlyGet = /*#__PURE__*/ createGetter(true)
const shallowReadonlyGet = /*#__PURE__*/ createGetter(true, true)

const arrayInstrumentations: Record<string, Function> = {}
;['includes', 'indexOf', 'lastIndexOf'].forEach(key => {
arrayInstrumentations[key] = function(...args: any[]): any {
const arr = toRaw(this) as any
for (let i = 0, l = (this as any).length; i < l; i++) {
;(['includes', 'indexOf', 'lastIndexOf'] as const).forEach(key => {
arrayInstrumentations[key] = function(this: unknown[], ...args: unknown[]) {
const arr = toRaw(this)
for (let i = 0, l = this.length; i < l; i++) {
track(arr, TrackOpTypes.GET, i + '')
}
// we run the method using the original args first (which may be reactive)
const res = arr[key](...args)
const res = (arr[key] as any)(...args)
if (res === -1 || res === false) {
// if that didn't work, run it again using raw values.
return arr[key](...args.map(toRaw))
return (arr[key] as any)(...args.map(toRaw))
} else {
return res
}
Expand Down
176 changes: 77 additions & 99 deletions packages/runtime-core/src/apiDefineComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -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<
Expand All @@ -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 }
Expand All @@ -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
Expand Down Expand Up @@ -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
}
})
27 changes: 24 additions & 3 deletions packages/runtime-core/src/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 }

Expand Down
39 changes: 26 additions & 13 deletions packages/runtime-core/src/componentOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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))
Expand Down
Loading

0 comments on commit 4fd468a

Please sign in to comment.