Skip to content

Commit 4fd468a

Browse files
authored
types(runtime-core): refactor defineComponent (#1883)
1 parent 848ccf5 commit 4fd468a

File tree

8 files changed

+583
-132
lines changed

8 files changed

+583
-132
lines changed

packages/reactivity/src/baseHandlers.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,17 @@ const readonlyGet = /*#__PURE__*/ createGetter(true)
3232
const shallowReadonlyGet = /*#__PURE__*/ createGetter(true, true)
3333

3434
const arrayInstrumentations: Record<string, Function> = {}
35-
;['includes', 'indexOf', 'lastIndexOf'].forEach(key => {
36-
arrayInstrumentations[key] = function(...args: any[]): any {
37-
const arr = toRaw(this) as any
38-
for (let i = 0, l = (this as any).length; i < l; i++) {
35+
;(['includes', 'indexOf', 'lastIndexOf'] as const).forEach(key => {
36+
arrayInstrumentations[key] = function(this: unknown[], ...args: unknown[]) {
37+
const arr = toRaw(this)
38+
for (let i = 0, l = this.length; i < l; i++) {
3939
track(arr, TrackOpTypes.GET, i + '')
4040
}
4141
// we run the method using the original args first (which may be reactive)
42-
const res = arr[key](...args)
42+
const res = (arr[key] as any)(...args)
4343
if (res === -1 || res === false) {
4444
// if that didn't work, run it again using raw values.
45-
return arr[key](...args.map(toRaw))
45+
return (arr[key] as any)(...args.map(toRaw))
4646
} else {
4747
return res
4848
}

packages/runtime-core/src/apiDefineComponent.ts

+77-99
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,65 @@ import {
66
ComponentOptionsWithObjectProps,
77
ComponentOptionsMixin,
88
RenderFunction,
9-
UnwrapAsyncBindings
9+
ComponentOptionsBase
1010
} from './componentOptions'
1111
import {
1212
SetupContext,
13-
FunctionalComponent,
1413
AllowedComponentProps,
1514
ComponentCustomProps
1615
} from './component'
17-
import {
18-
CreateComponentPublicInstance,
19-
ComponentPublicInstanceConstructor
20-
} from './componentPublicInstance'
2116
import { ExtractPropTypes, ComponentPropsOptions } from './componentProps'
2217
import { EmitsOptions } from './componentEmits'
2318
import { isFunction } from '@vue/shared'
2419
import { VNodeProps } from './vnode'
20+
import {
21+
CreateComponentPublicInstance,
22+
ComponentPublicInstanceConstructor
23+
} from './componentPublicInstance'
24+
25+
export type PublicProps = VNodeProps &
26+
AllowedComponentProps &
27+
ComponentCustomProps
28+
29+
export type DefineComponent<
30+
PropsOrPropOptions = any,
31+
RawBindings = any,
32+
D = any,
33+
C extends ComputedOptions = ComputedOptions,
34+
M extends MethodOptions = MethodOptions,
35+
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
36+
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
37+
E extends EmitsOptions = Record<string, any>,
38+
EE extends string = string,
39+
PP = PublicProps,
40+
RequiredProps = Readonly<ExtractPropTypes<PropsOrPropOptions>>,
41+
OptionalProps = Readonly<ExtractPropTypes<PropsOrPropOptions, false>>
42+
> = ComponentPublicInstanceConstructor<
43+
CreateComponentPublicInstance<
44+
OptionalProps,
45+
RawBindings,
46+
D,
47+
C,
48+
M,
49+
Mixin,
50+
Extends,
51+
E,
52+
PP & OptionalProps
53+
> &
54+
RequiredProps
55+
> &
56+
ComponentOptionsBase<
57+
RequiredProps,
58+
RawBindings,
59+
D,
60+
C,
61+
M,
62+
Mixin,
63+
Extends,
64+
E,
65+
EE
66+
> &
67+
PP
2568

2669
// defineComponent is a utility that is primarily used for type inference
2770
// when declaring components. Type inference is provided in the component
@@ -35,21 +78,7 @@ export function defineComponent<Props, RawBindings = object>(
3578
props: Readonly<Props>,
3679
ctx: SetupContext
3780
) => RawBindings | RenderFunction
38-
): ComponentPublicInstanceConstructor<
39-
CreateComponentPublicInstance<
40-
Props,
41-
UnwrapAsyncBindings<RawBindings>,
42-
{},
43-
{},
44-
{},
45-
{},
46-
{},
47-
{},
48-
// public props
49-
VNodeProps & Props & AllowedComponentProps & ComponentCustomProps
50-
>
51-
> &
52-
FunctionalComponent<Props>
81+
): DefineComponent<Props, RawBindings>
5382

5483
// overload 2: object format with no props
5584
// (uses user defined props interface)
@@ -58,11 +87,11 @@ export function defineComponent<
5887
Props = {},
5988
RawBindings = {},
6089
D = {},
61-
C extends ComputedOptions = {},
62-
M extends MethodOptions = {},
90+
C extends ComputedOptions = ComputedOptions,
91+
M extends MethodOptions = MethodOptions,
6392
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
6493
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
65-
E extends EmitsOptions = Record<string, any>,
94+
E extends EmitsOptions = EmitsOptions,
6695
EE extends string = string
6796
>(
6897
options: ComponentOptionsWithoutProps<
@@ -76,30 +105,7 @@ export function defineComponent<
76105
E,
77106
EE
78107
>
79-
): ComponentPublicInstanceConstructor<
80-
CreateComponentPublicInstance<
81-
Props,
82-
UnwrapAsyncBindings<RawBindings>,
83-
D,
84-
C,
85-
M,
86-
Mixin,
87-
Extends,
88-
E,
89-
VNodeProps & Props & AllowedComponentProps & ComponentCustomProps
90-
>
91-
> &
92-
ComponentOptionsWithoutProps<
93-
Props,
94-
RawBindings,
95-
D,
96-
C,
97-
M,
98-
Mixin,
99-
Extends,
100-
E,
101-
EE
102-
>
108+
): DefineComponent<Props, RawBindings, D, C, M, Mixin, Extends, E, EE>
103109

104110
// overload 3: object format with array props declaration
105111
// props inferred as { [key in PropNames]?: any }
@@ -126,32 +132,17 @@ export function defineComponent<
126132
E,
127133
EE
128134
>
129-
): ComponentPublicInstanceConstructor<
130-
// array props technically doesn't place any constraints on props in TSX before,
131-
// but now we can export array props in TSX
132-
CreateComponentPublicInstance<
133-
Readonly<{ [key in PropNames]?: any }>,
134-
UnwrapAsyncBindings<RawBindings>,
135-
D,
136-
C,
137-
M,
138-
Mixin,
139-
Extends,
140-
E,
141-
AllowedComponentProps & ComponentCustomProps
142-
>
143-
> &
144-
ComponentOptionsWithArrayProps<
145-
PropNames,
146-
RawBindings,
147-
D,
148-
C,
149-
M,
150-
Mixin,
151-
Extends,
152-
E,
153-
EE
154-
>
135+
): DefineComponent<
136+
Readonly<{ [key in PropNames]?: any }>,
137+
RawBindings,
138+
D,
139+
C,
140+
M,
141+
Mixin,
142+
Extends,
143+
E,
144+
EE
145+
>
155146

156147
// overload 4: object format with object props declaration
157148
// see `ExtractPropTypes` in ./componentProps.ts
@@ -179,33 +170,20 @@ export function defineComponent<
179170
E,
180171
EE
181172
>
182-
): ComponentPublicInstanceConstructor<
183-
CreateComponentPublicInstance<
184-
ExtractPropTypes<PropsOptions, false>,
185-
UnwrapAsyncBindings<RawBindings>,
186-
D,
187-
C,
188-
M,
189-
Mixin,
190-
Extends,
191-
E,
192-
VNodeProps & AllowedComponentProps & ComponentCustomProps
193-
> &
194-
Readonly<ExtractPropTypes<PropsOptions>>
195-
> &
196-
ComponentOptionsWithObjectProps<
197-
PropsOptions,
198-
RawBindings,
199-
D,
200-
C,
201-
M,
202-
Mixin,
203-
Extends,
204-
E,
205-
EE
206-
>
173+
): DefineComponent<PropsOptions, RawBindings, D, C, M, Mixin, Extends, E, EE>
207174

208175
// implementation, close to no-op
209176
export function defineComponent(options: unknown) {
210177
return isFunction(options) ? { setup: options, name: options.name } : options
211178
}
179+
180+
defineComponent({
181+
async setup() {
182+
return {
183+
a: 123
184+
}
185+
},
186+
render() {
187+
this.a
188+
}
189+
})

packages/runtime-core/src/component.ts

+24-3
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,12 @@ import { warn } from './warning'
2626
import { ErrorCodes, callWithErrorHandling } from './errorHandling'
2727
import { AppContext, createAppContext, AppConfig } from './apiCreateApp'
2828
import { Directive, validateDirectiveName } from './directives'
29-
import { applyOptions, ComponentOptions } from './componentOptions'
29+
import {
30+
applyOptions,
31+
ComponentOptions,
32+
ComputedOptions,
33+
MethodOptions
34+
} from './componentOptions'
3035
import {
3136
EmitsOptions,
3237
ObjectEmitsOptions,
@@ -118,13 +123,29 @@ export interface ClassComponent {
118123
* values, e.g. checking if its a function or not. This is mostly for internal
119124
* implementation code.
120125
*/
121-
export type ConcreteComponent = ComponentOptions | FunctionalComponent<any, any>
126+
export type ConcreteComponent<
127+
Props = {},
128+
RawBindings = any,
129+
D = any,
130+
C extends ComputedOptions = ComputedOptions,
131+
M extends MethodOptions = MethodOptions
132+
> =
133+
| ComponentOptions<Props, RawBindings, D, C, M>
134+
| FunctionalComponent<Props, any>
122135

123136
/**
124137
* A type used in public APIs where a component type is expected.
125138
* The constructor type is an artificial type returned by defineComponent().
126139
*/
127-
export type Component = ConcreteComponent | ComponentPublicInstanceConstructor
140+
export type Component<
141+
Props = any,
142+
RawBindings = any,
143+
D = any,
144+
C extends ComputedOptions = ComputedOptions,
145+
M extends MethodOptions = MethodOptions
146+
> =
147+
| ConcreteComponent<Props, RawBindings, D, C, M>
148+
| ComponentPublicInstanceConstructor<Props>
128149

129150
export { ComponentOptions }
130151

packages/runtime-core/src/componentOptions.ts

+26-13
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,6 @@ export interface ComponentCustomOptions {}
7272

7373
export type RenderFunction = () => VNodeChild
7474

75-
export type UnwrapAsyncBindings<T> = T extends Promise<infer S> ? S : T
76-
7775
export interface ComponentOptionsBase<
7876
Props,
7977
RawBindings,
@@ -92,7 +90,7 @@ export interface ComponentOptionsBase<
9290
this: void,
9391
props: Props,
9492
ctx: SetupContext<E>
95-
) => RawBindings | RenderFunction | void
93+
) => Promise<RawBindings> | RawBindings | RenderFunction | void
9694
name?: string
9795
template?: string | object // can be a direct DOM node
9896
// Note: we are intentionally using the signature-less `Function` type here
@@ -230,10 +228,29 @@ export type ComponentOptionsWithObjectProps<
230228
>
231229
>
232230

233-
export type ComponentOptions =
234-
| ComponentOptionsWithoutProps<any, any, any, any, any>
235-
| ComponentOptionsWithObjectProps<any, any, any, any, any>
236-
| ComponentOptionsWithArrayProps<any, any, any, any, any>
231+
export type ComponentOptions<
232+
Props = {},
233+
RawBindings = any,
234+
D = any,
235+
C extends ComputedOptions = any,
236+
M extends MethodOptions = any,
237+
Mixin extends ComponentOptionsMixin = any,
238+
Extends extends ComponentOptionsMixin = any,
239+
E extends EmitsOptions = any
240+
> = ComponentOptionsBase<Props, RawBindings, D, C, M, Mixin, Extends, E> &
241+
ThisType<
242+
CreateComponentPublicInstance<
243+
{},
244+
RawBindings,
245+
D,
246+
C,
247+
M,
248+
Mixin,
249+
Extends,
250+
E,
251+
Readonly<Props>
252+
>
253+
>
237254

238255
export type ComponentOptionsMixin = ComponentOptionsBase<
239256
any,
@@ -638,17 +655,13 @@ export function applyOptions(
638655
onRenderTriggered(renderTriggered.bind(publicThis))
639656
}
640657
if (__DEV__ && beforeDestroy) {
641-
warn(
642-
`\`beforeDestroy\` has been renamed to \`beforeUnmount\`.`
643-
)
658+
warn(`\`beforeDestroy\` has been renamed to \`beforeUnmount\`.`)
644659
}
645660
if (beforeUnmount) {
646661
onBeforeUnmount(beforeUnmount.bind(publicThis))
647662
}
648663
if (__DEV__ && destroyed) {
649-
warn(
650-
`\`destroyed\` has been renamed to \`unmounted\`.`
651-
)
664+
warn(`\`destroyed\` has been renamed to \`unmounted\`.`)
652665
}
653666
if (unmounted) {
654667
onUnmounted(unmounted.bind(publicThis))

0 commit comments

Comments
 (0)