Skip to content

Commit f3a9b51

Browse files
authoredApr 24, 2020
fix(types): make return type of defineComponent assignable to Component type (#1032)
fix #993
1 parent 28b4c31 commit f3a9b51

File tree

4 files changed

+49
-10
lines changed

4 files changed

+49
-10
lines changed
 

‎packages/runtime-core/__tests__/components/Suspense.spec.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import {
1111
watch,
1212
watchEffect,
1313
onUnmounted,
14-
onErrorCaptured
14+
onErrorCaptured,
15+
Component
1516
} from '@vue/runtime-test'
1617

1718
describe('Suspense', () => {
@@ -30,7 +31,7 @@ describe('Suspense', () => {
3031
setup(props: any, { slots }: any) {
3132
const p = new Promise(resolve => {
3233
setTimeout(() => {
33-
resolve(() => h(comp, props, slots))
34+
resolve(() => h<Component>(comp, props, slots))
3435
}, delay)
3536
})
3637
// in Node 12, due to timer/nextTick mechanism change, we have to wait

‎packages/runtime-core/src/apiDefineComponent.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
ComponentOptionsWithArrayProps,
66
ComponentOptionsWithObjectProps
77
} from './componentOptions'
8-
import { SetupContext, RenderFunction } from './component'
8+
import { SetupContext, RenderFunction, FunctionalComponent } from './component'
99
import { ComponentPublicInstance } from './componentProxy'
1010
import { ExtractPropTypes, ComponentPropsOptions } from './componentProps'
1111
import { EmitsOptions } from './componentEmits'
@@ -34,7 +34,7 @@ export function defineComponent<Props, RawBindings = object>(
3434
// public props
3535
VNodeProps & Props
3636
>
37-
}
37+
} & FunctionalComponent<Props>
3838

3939
// overload 2: object format with no props
4040
// (uses user defined props interface)
@@ -59,7 +59,7 @@ export function defineComponent<
5959
E,
6060
VNodeProps & Props
6161
>
62-
}
62+
} & ComponentOptionsWithoutProps<Props, RawBindings, D, C, M, E, EE>
6363

6464
// overload 3: object format with array props declaration
6565
// props inferred as { [key in PropNames]?: any }
@@ -85,7 +85,7 @@ export function defineComponent<
8585
): {
8686
// array props technically doesn't place any contraints on props in TSX
8787
new (): ComponentPublicInstance<VNodeProps, RawBindings, D, C, M, E>
88-
}
88+
} & ComponentOptionsWithArrayProps<PropNames, RawBindings, D, C, M, E, EE>
8989

9090
// overload 4: object format with object props declaration
9191
// see `ExtractPropTypes` in ./componentProps.ts
@@ -119,7 +119,7 @@ export function defineComponent<
119119
E,
120120
VNodeProps & ExtractPropTypes<PropsOptions, false>
121121
>
122-
}
122+
} & ComponentOptionsWithObjectProps<PropsOptions, RawBindings, D, C, M, E, EE>
123123

124124
// implementation, close to no-op
125125
export function defineComponent(options: unknown) {

‎packages/runtime-core/src/h.ts

+9-2
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ interface Constructor<P = any> {
6767
new (): { $props: P }
6868
}
6969

70+
// Excludes Component type from returned `defineComponent`
71+
type NotDefinedComponent<T extends Component> = T extends Constructor
72+
? never
73+
: T
74+
7075
// The following is a series of overloads for providing props validation of
7176
// manually written render functions.
7277

@@ -110,8 +115,10 @@ export function h<P>(
110115

111116
// catch-all for generic component types
112117
export function h(type: Component, children?: RawChildren): VNode
113-
export function h(
114-
type: ComponentOptions | FunctionalComponent<{}>,
118+
119+
// exclude `defineComponent`
120+
export function h<Options extends ComponentOptions | FunctionalComponent<{}>>(
121+
type: NotDefinedComponent<Options>,
115122
props?: RawProps | null,
116123
children?: RawChildren | RawSlots
117124
): VNode

‎test-dts/h.test-d.ts

+32-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { expectError } from 'tsd'
1+
import { expectError, expectAssignable } from 'tsd'
22
import {
33
describe,
44
h,
@@ -131,3 +131,34 @@ describe('h support for generic component type', () => {
131131
}
132132
foo({})
133133
})
134+
135+
// #993
136+
describe('describeComponent extends Component', () => {
137+
// functional
138+
expectAssignable<Component>(
139+
defineComponent((_props: { foo?: string; bar: number }) => {})
140+
)
141+
142+
// typed props
143+
expectAssignable<Component>(defineComponent({}))
144+
145+
// prop arrays
146+
expectAssignable<Component>(
147+
defineComponent({
148+
props: ['a', 'b']
149+
})
150+
)
151+
152+
// prop object
153+
expectAssignable<Component>(
154+
defineComponent({
155+
props: {
156+
foo: String,
157+
bar: {
158+
type: Number,
159+
required: true
160+
}
161+
}
162+
})
163+
)
164+
})

0 commit comments

Comments
 (0)
Please sign in to comment.