From b44003eb049853611936dea2bc3168d745c93d6f Mon Sep 17 00:00:00 2001 From: zcf0508 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 7e6d1968ca..3e517a40a1 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 e2da34e753..7a6416727a 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: Readonly>, ctx: SetupContext ) => RawBindings | (() => VNode | null) | void diff --git a/types/v3-component-public-instance.d.ts b/types/v3-component-public-instance.d.ts index 1c55908ac7..4468cc76b3 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, PublicProps, E, Defaults, diff --git a/types/v3-setup-context.d.ts b/types/v3-setup-context.d.ts index 77b49bed8a..f6bee6431b 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 string[] + ? { + [K in string & `on${Capitalize}`]?: (...args: any[]) => any + } + : T extends ObjectEmitsOptions + ? { + [K in string & + `on${Capitalize}`]?: K extends `on${infer C}` + ? T[Uncapitalize] extends null + ? (...args: any[]) => any + : ( + ...args: T[Uncapitalize] 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 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 3e517a40a1..0dfb162f5c 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 4468cc76b3..1c55908ac7 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, + P, PublicProps, E, Defaults, diff --git a/types/v3-define-component.d.ts b/types/v3-define-component.d.ts index 03ef52d185..c21bb4a7a6 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) & EmitsToProps >, Defaults = ExtractDefaultPropTypes > = ComponentPublicInstanceConstructor<