Explorar o código

fix(types): fix functional component for `h` (#9991)

- stricter children/slots type
- fix emits/`EE` type argument of `FunctionalComponent`
三咲智子 Kevin Deng %!s(int64=2) %!d(string=hai) anos
pai
achega
438a74aad8
Modificáronse 2 ficheiros con 28 adicións e 4 borrados
  1. 24 0
      packages/dts-test/h.test-d.ts
  2. 4 4
      packages/runtime-core/src/h.ts

+ 24 - 0
packages/dts-test/h.test-d.ts

@@ -2,8 +2,10 @@ import {
   type Component,
   type Component,
   type DefineComponent,
   type DefineComponent,
   Fragment,
   Fragment,
+  type FunctionalComponent,
   Suspense,
   Suspense,
   Teleport,
   Teleport,
+  type VNode,
   defineComponent,
   defineComponent,
   h,
   h,
   ref,
   ref,
@@ -77,6 +79,19 @@ describe('h inference w/ Suspense', () => {
   h(Suspense, { onResolve: 1 })
   h(Suspense, { onResolve: 1 })
 })
 })
 
 
+declare const fc: FunctionalComponent<
+  {
+    foo: string
+    bar?: number
+    onClick: (evt: MouseEvent) => void
+  },
+  ['click'],
+  {
+    default: () => VNode
+    title: (scope: { id: number }) => VNode
+  }
+>
+declare const vnode: VNode
 describe('h inference w/ functional component', () => {
 describe('h inference w/ functional component', () => {
   const Func = (_props: { foo: string; bar?: number }) => ''
   const Func = (_props: { foo: string; bar?: number }) => ''
   h(Func, { foo: 'hello' })
   h(Func, { foo: 'hello' })
@@ -87,6 +102,15 @@ describe('h inference w/ functional component', () => {
   h(Func, {})
   h(Func, {})
   //  @ts-expect-error
   //  @ts-expect-error
   h(Func, { bar: 123 })
   h(Func, { bar: 123 })
+
+  h(
+    fc,
+    { foo: 'hello', onClick: () => {} },
+    {
+      default: () => vnode,
+      title: ({ id }: { id: number }) => vnode,
+    },
+  )
 })
 })
 
 
 describe('h support w/ plain object component', () => {
 describe('h support w/ plain object component', () => {

+ 4 - 4
packages/runtime-core/src/h.ts

@@ -10,7 +10,7 @@ import {
 } from './vnode'
 } from './vnode'
 import type { Teleport, TeleportProps } from './components/Teleport'
 import type { Teleport, TeleportProps } from './components/Teleport'
 import type { Suspense, SuspenseProps } from './components/Suspense'
 import type { Suspense, SuspenseProps } from './components/Suspense'
-import { isArray, isObject } from '@vue/shared'
+import { type IfAny, isArray, isObject } from '@vue/shared'
 import type { RawSlots } from './componentSlots'
 import type { RawSlots } from './componentSlots'
 import type {
 import type {
   Component,
   Component,
@@ -140,11 +140,11 @@ export function h(
 export function h<
 export function h<
   P,
   P,
   E extends EmitsOptions = {},
   E extends EmitsOptions = {},
-  S extends Record<string, any> = {},
+  S extends Record<string, any> = any,
 >(
 >(
-  type: FunctionalComponent<P, E, S>,
+  type: FunctionalComponent<P, any, S, any>,
   props?: (RawProps & P) | ({} extends P ? null : never),
   props?: (RawProps & P) | ({} extends P ? null : never),
-  children?: RawChildren | RawSlots,
+  children?: RawChildren | IfAny<S, RawSlots, S>,
 ): VNode
 ): VNode
 
 
 // catch-all for generic component types
 // catch-all for generic component types