From b44003eb049853611936dea2bc3168d745c93d6f Mon Sep 17 00:00:00 2001
From: zcf0508 <zcf0508@live.com>
Date: Fri, 15 Dec 2023 13:54:42 +0800
Subject: [PATCH 1/2] fix(type): convert emits to props

---
 types/test/v3/define-component-test.tsx | 13 +++++++++++++
 types/v3-component-options.d.ts         |  4 ++--
 types/v3-component-public-instance.d.ts |  4 ++--
 types/v3-setup-context.d.ts             | 19 +++++++++++++++++++
 4 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/types/test/v3/define-component-test.tsx b/types/test/v3/define-component-test.tsx
index 7e6d1968ca3..3e517a40a17 100644
--- a/types/test/v3/define-component-test.tsx
+++ b/types/test/v3/define-component-test.tsx
@@ -966,6 +966,19 @@ describe('emits', () => {
       }
     }
   })
+
+  // should have `onXXX` props for emits
+  defineComponent({
+    props: {
+      bar: String
+    },
+    emits: {
+      foo: (n: number) => n > 0
+    },
+    setup(props) {
+      expectType<((n: number) => boolean) | undefined>(props.onFoo)
+    }
+  })
 })
 
 // describe('componentOptions setup should be `SetupContext`', () => {
diff --git a/types/v3-component-options.d.ts b/types/v3-component-options.d.ts
index e2da34e753f..7a6416727a0 100644
--- a/types/v3-component-options.d.ts
+++ b/types/v3-component-options.d.ts
@@ -1,7 +1,7 @@
 import { Vue } from './vue'
 import { VNode } from './vnode'
 import { ComponentOptions as Vue2ComponentOptions } from './options'
-import { EmitsOptions, SetupContext } from './v3-setup-context'
+import { EmitsOptions, EmitsToProps, SetupContext } from './v3-setup-context'
 import { Data, LooseRequired, UnionToIntersection } from './common'
 import {
   ComponentPropsOptions,
@@ -52,7 +52,7 @@ export type SetupFunction<
   Emits extends EmitsOptions = {}
 > = (
   this: void,
-  props: Readonly<Props>,
+  props: Readonly<Props & EmitsToProps<Emits>>,
   ctx: SetupContext<Emits>
 ) => RawBindings | (() => VNode | null) | void
 
diff --git a/types/v3-component-public-instance.d.ts b/types/v3-component-public-instance.d.ts
index 1c55908ac73..4468cc76b38 100644
--- a/types/v3-component-public-instance.d.ts
+++ b/types/v3-component-public-instance.d.ts
@@ -13,7 +13,7 @@ import {
   ComponentOptionsMixin,
   ComponentOptionsBase
 } from './v3-component-options'
-import { EmitFn, EmitsOptions } from './v3-setup-context'
+import { EmitFn, EmitsOptions, EmitsToProps } from './v3-setup-context'
 
 /**
  * Custom properties added to component instances in any way and can be accessed through `this`
@@ -150,7 +150,7 @@ export type ComponentPublicInstance<
   >
 > = Vue3Instance<
   D,
-  P,
+  P & EmitsToProps<E>,
   PublicProps,
   E,
   Defaults,
diff --git a/types/v3-setup-context.d.ts b/types/v3-setup-context.d.ts
index 77b49bed8a6..f6bee6431b8 100644
--- a/types/v3-setup-context.d.ts
+++ b/types/v3-setup-context.d.ts
@@ -13,6 +13,25 @@ export type ObjectEmitsOptions = Record<
 
 export type EmitsOptions = ObjectEmitsOptions | string[]
 
+export type EmitsToProps<T extends EmitsOptions> = T extends string[]
+  ? {
+      [K in string & `on${Capitalize<T[number]>}`]?: (...args: any[]) => any
+    }
+  : T extends ObjectEmitsOptions
+  ? {
+      [K in string &
+        `on${Capitalize<string & keyof T>}`]?: K extends `on${infer C}`
+        ? T[Uncapitalize<C>] extends null
+          ? (...args: any[]) => any
+          : (
+              ...args: T[Uncapitalize<C>] extends (...args: infer P) => any
+                ? P
+                : never
+            ) => any
+        : never
+    }
+  : {}
+
 export type EmitFn<
   Options = ObjectEmitsOptions,
   Event extends keyof Options = keyof Options,

From 29518ef9697cf0459e42e5e760a7be0e2783c695 Mon Sep 17 00:00:00 2001
From: zcf0508 <zcf0508@live.com>
Date: Mon, 18 Dec 2023 14:27:04 +0800
Subject: [PATCH 2/2] feat: support extends and mixins

---
 types/test/v3/define-component-test.tsx | 30 ++++++++++++++++++++++++-
 types/v3-component-public-instance.d.ts |  4 ++--
 types/v3-define-component.d.ts          |  6 ++---
 3 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/types/test/v3/define-component-test.tsx b/types/test/v3/define-component-test.tsx
index 3e517a40a17..0dfb162f5c6 100644
--- a/types/test/v3/define-component-test.tsx
+++ b/types/test/v3/define-component-test.tsx
@@ -968,7 +968,7 @@ describe('emits', () => {
   })
 
   // should have `onXXX` props for emits
-  defineComponent({
+  const a = defineComponent({
     props: {
       bar: String
     },
@@ -979,6 +979,34 @@ describe('emits', () => {
       expectType<((n: number) => boolean) | undefined>(props.onFoo)
     }
   })
+
+  const b = defineComponent({
+    extends: a,
+    props: {
+      bar2: String
+    },
+    emits: {
+      foo2: (n: number) => n > 0
+    },
+    setup(props) {
+      expectType<((n: number) => boolean) | undefined>(props.onFoo)
+    }
+  })
+
+  defineComponent({
+    mixins: [a, b],
+    props: {
+      bar3: String
+    },
+    emits: {
+      foo3: (n: number) => n > 0
+    },
+    setup(props) {
+      expectType<((n: number) => boolean) | undefined>(props.onFoo)
+      expectType<((n: number) => boolean) | undefined>(props.onFoo2)
+      expectType<((n: number) => boolean) | undefined>(props.onFoo3)
+    }
+  })
 })
 
 // describe('componentOptions setup should be `SetupContext`', () => {
diff --git a/types/v3-component-public-instance.d.ts b/types/v3-component-public-instance.d.ts
index 4468cc76b38..1c55908ac73 100644
--- a/types/v3-component-public-instance.d.ts
+++ b/types/v3-component-public-instance.d.ts
@@ -13,7 +13,7 @@ import {
   ComponentOptionsMixin,
   ComponentOptionsBase
 } from './v3-component-options'
-import { EmitFn, EmitsOptions, EmitsToProps } from './v3-setup-context'
+import { EmitFn, EmitsOptions } from './v3-setup-context'
 
 /**
  * Custom properties added to component instances in any way and can be accessed through `this`
@@ -150,7 +150,7 @@ export type ComponentPublicInstance<
   >
 > = Vue3Instance<
   D,
-  P & EmitsToProps<E>,
+  P,
   PublicProps,
   E,
   Defaults,
diff --git a/types/v3-define-component.d.ts b/types/v3-define-component.d.ts
index 03ef52d1856..c21bb4a7a65 100644
--- a/types/v3-define-component.d.ts
+++ b/types/v3-define-component.d.ts
@@ -17,7 +17,7 @@ import {
   CreateComponentPublicInstance
 } from './v3-component-public-instance'
 import { Data, HasDefined } from './common'
-import { EmitsOptions } from './v3-setup-context'
+import { EmitsOptions, EmitsToProps } from './v3-setup-context'
 import { CreateElement, RenderContext } from './umd'
 
 export type DefineComponent<
@@ -31,9 +31,9 @@ export type DefineComponent<
   E extends EmitsOptions = {},
   EE extends string = string,
   Props = Readonly<
-    PropsOrPropOptions extends ComponentPropsOptions
+    (PropsOrPropOptions extends ComponentPropsOptions
       ? ExtractPropTypes<PropsOrPropOptions>
-      : PropsOrPropOptions
+      : PropsOrPropOptions) & EmitsToProps<E>
   >,
   Defaults = ExtractDefaultPropTypes<PropsOrPropOptions>
 > = ComponentPublicInstanceConstructor<