]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(types): make return type of `defineComponent` assignable to `Component` type...
authorCarlos Rodrigues <carlos@hypermob.co.uk>
Fri, 24 Apr 2020 17:22:58 +0000 (18:22 +0100)
committerGitHub <noreply@github.com>
Fri, 24 Apr 2020 17:22:58 +0000 (13:22 -0400)
fix #993

packages/runtime-core/__tests__/components/Suspense.spec.ts
packages/runtime-core/src/apiDefineComponent.ts
packages/runtime-core/src/h.ts
test-dts/h.test-d.ts

index 5b71689a4356722bb334824683700a3b1974c15c..cb8ece4873e5d4d6633aa6602e128fa6a85ee9a8 100644 (file)
@@ -11,7 +11,8 @@ import {
   watch,
   watchEffect,
   onUnmounted,
-  onErrorCaptured
+  onErrorCaptured,
+  Component
 } from '@vue/runtime-test'
 
 describe('Suspense', () => {
@@ -30,7 +31,7 @@ describe('Suspense', () => {
       setup(props: any, { slots }: any) {
         const p = new Promise(resolve => {
           setTimeout(() => {
-            resolve(() => h(comp, props, slots))
+            resolve(() => h<Component>(comp, props, slots))
           }, delay)
         })
         // in Node 12, due to timer/nextTick mechanism change, we have to wait
index 083f0dd655a3c293635aa8e63d77ed1f6eae7d12..c235e30c3880473afb2f9b7ce738396616d4ada5 100644 (file)
@@ -5,7 +5,7 @@ import {
   ComponentOptionsWithArrayProps,
   ComponentOptionsWithObjectProps
 } from './componentOptions'
-import { SetupContext, RenderFunction } from './component'
+import { SetupContext, RenderFunction, FunctionalComponent } from './component'
 import { ComponentPublicInstance } from './componentProxy'
 import { ExtractPropTypes, ComponentPropsOptions } from './componentProps'
 import { EmitsOptions } from './componentEmits'
@@ -34,7 +34,7 @@ export function defineComponent<Props, RawBindings = object>(
     // public props
     VNodeProps & Props
   >
-}
+} & FunctionalComponent<Props>
 
 // overload 2: object format with no props
 // (uses user defined props interface)
@@ -59,7 +59,7 @@ export function defineComponent<
     E,
     VNodeProps & Props
   >
-}
+} & ComponentOptionsWithoutProps<Props, RawBindings, D, C, M, E, EE>
 
 // overload 3: object format with array props declaration
 // props inferred as { [key in PropNames]?: any }
@@ -85,7 +85,7 @@ export function defineComponent<
 ): {
   // array props technically doesn't place any contraints on props in TSX
   new (): ComponentPublicInstance<VNodeProps, RawBindings, D, C, M, E>
-}
+} & ComponentOptionsWithArrayProps<PropNames, RawBindings, D, C, M, E, EE>
 
 // overload 4: object format with object props declaration
 // see `ExtractPropTypes` in ./componentProps.ts
@@ -119,7 +119,7 @@ export function defineComponent<
     E,
     VNodeProps & ExtractPropTypes<PropsOptions, false>
   >
-}
+} & ComponentOptionsWithObjectProps<PropsOptions, RawBindings, D, C, M, E, EE>
 
 // implementation, close to no-op
 export function defineComponent(options: unknown) {
index 099fe38057d1598a183789014464c84b594993e5..aebd8506f5d05d2a0669f951297885849f1acde6 100644 (file)
@@ -67,6 +67,11 @@ interface Constructor<P = any> {
   new (): { $props: P }
 }
 
+// Excludes Component type from returned `defineComponent`
+type NotDefinedComponent<T extends Component> = T extends Constructor
+  ? never
+  : T
+
 // The following is a series of overloads for providing props validation of
 // manually written render functions.
 
@@ -110,8 +115,10 @@ export function h<P>(
 
 // catch-all for generic component types
 export function h(type: Component, children?: RawChildren): VNode
-export function h(
-  type: ComponentOptions | FunctionalComponent<{}>,
+
+// exclude `defineComponent`
+export function h<Options extends ComponentOptions | FunctionalComponent<{}>>(
+  type: NotDefinedComponent<Options>,
   props?: RawProps | null,
   children?: RawChildren | RawSlots
 ): VNode
index 338e1fc36f3d3de484c32e96ba66a5872cea0916..88b1a0252475de6a36cabc6302801b3babc5335c 100644 (file)
@@ -1,4 +1,4 @@
-import { expectError } from 'tsd'
+import { expectError, expectAssignable } from 'tsd'
 import {
   describe,
   h,
@@ -131,3 +131,34 @@ describe('h support for generic component type', () => {
   }
   foo({})
 })
+
+// #993
+describe('describeComponent extends Component', () => {
+  // functional
+  expectAssignable<Component>(
+    defineComponent((_props: { foo?: string; bar: number }) => {})
+  )
+
+  // typed props
+  expectAssignable<Component>(defineComponent({}))
+
+  // prop arrays
+  expectAssignable<Component>(
+    defineComponent({
+      props: ['a', 'b']
+    })
+  )
+
+  // prop object
+  expectAssignable<Component>(
+    defineComponent({
+      props: {
+        foo: String,
+        bar: {
+          type: Number,
+          required: true
+        }
+      }
+    })
+  )
+})