From c34b024864911056a778eba4db42f3799cb8d0cb Mon Sep 17 00:00:00 2001 From: Evan You Date: Thu, 25 Apr 2024 23:28:58 +0800 Subject: [PATCH 1/6] feat(types): provide internal options for directly using user prop types in language tools --- packages/dts-test/defineComponent.test-d.tsx | 33 +++++++++ .../runtime-core/src/apiDefineComponent.ts | 73 +++++++++++++++++-- packages/runtime-core/src/componentOptions.ts | 59 +++++++++++++++ 3 files changed, 159 insertions(+), 6 deletions(-) diff --git a/packages/dts-test/defineComponent.test-d.tsx b/packages/dts-test/defineComponent.test-d.tsx index 44a00d4e586..d06608a66d5 100644 --- a/packages/dts-test/defineComponent.test-d.tsx +++ b/packages/dts-test/defineComponent.test-d.tsx @@ -1623,3 +1623,36 @@ declare const MyButton: DefineComponent< {} > ; + +describe('__typeProps backdoor for union type for conditional props', () => { + interface CommonProps { + size?: 'xl' | 'l' | 'm' | 's' | 'xs' + } + + type ConditionalProps = + | { + color?: 'normal' | 'primary' | 'secondary' + appearance?: 'normal' | 'outline' | 'text' + } + | { + color: 'white' + appearance: 'outline' + } + + type Props = CommonProps & ConditionalProps + + const Comp = defineComponent({ + __typeProps: {} as Props, + }) + // @ts-expect-error + ; + // @ts-expect-error + ; + + const c = new Comp() + // @ts-expect-error + c.$props = { color: 'white' } + // @ts-expect-error + c.$props = { color: 'white', appearance: 'text' } + c.$props = { color: 'white', appearance: 'outline' } +}) diff --git a/packages/runtime-core/src/apiDefineComponent.ts b/packages/runtime-core/src/apiDefineComponent.ts index 46e1d59a8e7..5735cb803ff 100644 --- a/packages/runtime-core/src/apiDefineComponent.ts +++ b/packages/runtime-core/src/apiDefineComponent.ts @@ -5,6 +5,7 @@ import type { ComponentOptionsMixin, ComponentOptionsWithArrayProps, ComponentOptionsWithObjectProps, + ComponentOptionsWithTypeProps, ComponentOptionsWithoutProps, ComponentProvideOptions, ComputedOptions, @@ -64,6 +65,7 @@ export type DefineComponent< Directives extends Record = {}, Exposed extends string = string, Provide extends ComponentProvideOptions = ComponentProvideOptions, + MakeDefaultsOptional extends boolean = true, > = ComponentPublicInstanceConstructor< CreateComponentPublicInstance< Props, @@ -76,7 +78,7 @@ export type DefineComponent< E, PP & Props, Defaults, - true, + MakeDefaultsOptional, {}, S, LC & GlobalComponents, @@ -169,9 +171,68 @@ export function defineComponent< }, ): DefineSetupFnComponent -// overload 2: object format with no props +// overload 2: object format with internal type props +// backdoor for Vue Language Service +export function defineComponent< + Props = {}, + RawBindings = {}, + D = {}, + C extends ComputedOptions = {}, + M extends MethodOptions = {}, + Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, + Extends extends ComponentOptionsMixin = ComponentOptionsMixin, + E extends EmitsOptions = {}, + EE extends string = string, + I extends ComponentInjectOptions = {}, + II extends string = string, + S extends SlotsType = {}, + LC extends Record = {}, + Directives extends Record = {}, + Exposed extends string = string, + Provide extends ComponentProvideOptions = ComponentProvideOptions, +>( + options: ComponentOptionsWithTypeProps< + Props, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + EE, + I, + II, + S, + LC, + Directives, + Exposed, + Provide + >, +): DefineComponent< + Props, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + EE, + PublicProps, + ResolveProps, + ExtractDefaultPropTypes, + S, + LC, + Directives, + Exposed, + Provide, + false +> + +// overload 3: object format with no props // (uses user defined props interface) -// return type is for Vetur and TSX support +// return type is for language-tools and TSX support export function defineComponent< Props = {}, RawBindings = {}, @@ -228,9 +289,9 @@ export function defineComponent< Provide > -// overload 3: object format with array props declaration +// overload 4: object format with array props declaration // props inferred as { [key in PropNames]?: any } -// return type is for Vetur and TSX support +// return type is for language-tools and TSX support export function defineComponent< PropNames extends string, RawBindings, @@ -288,7 +349,7 @@ export function defineComponent< Provide > -// overload 4: object format with object props declaration +// overload 5: object format with object props declaration // see `ExtractPropTypes` in ./componentProps.ts export function defineComponent< // the Readonly constraint allows TS to treat the type of { required: true } diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index da1dfcec0cc..64c15b5fe1c 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -218,6 +218,65 @@ export interface RuntimeCompilerOptions { delimiters?: [string, string] } +export type ComponentOptionsWithTypeProps< + Props = {}, + RawBindings = {}, + D = {}, + C extends ComputedOptions = {}, + M extends MethodOptions = {}, + Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, + Extends extends ComponentOptionsMixin = ComponentOptionsMixin, + E extends EmitsOptions = EmitsOptions, + EE extends string = string, + I extends ComponentInjectOptions = {}, + II extends string = string, + S extends SlotsType = {}, + LC extends Record = {}, + Directives extends Record = {}, + Exposed extends string = string, + Provide extends ComponentProvideOptions = ComponentProvideOptions, + PE = Props & EmitsToProps, +> = ComponentOptionsBase< + PE, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + EE, + {}, + I, + II, + S, + LC, + Directives, + Exposed, + Provide +> & { + __typeProps: Props +} & ThisType< + CreateComponentPublicInstance< + PE, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + EE, + {}, + false, + I, + S, + LC, + Directives, + Exposed + > + > + export type ComponentOptionsWithoutProps< Props = {}, RawBindings = {}, From e610a86a83639a3c9018bda8c908a32b2b4dd6cf Mon Sep 17 00:00:00 2001 From: Evan You Date: Fri, 26 Apr 2024 14:52:23 +0800 Subject: [PATCH 2/6] chore: remove unnecessary generics argument --- packages/dts-test/defineComponent.test-d.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dts-test/defineComponent.test-d.tsx b/packages/dts-test/defineComponent.test-d.tsx index d06608a66d5..6fc5e9cc983 100644 --- a/packages/dts-test/defineComponent.test-d.tsx +++ b/packages/dts-test/defineComponent.test-d.tsx @@ -1641,7 +1641,7 @@ describe('__typeProps backdoor for union type for conditional props', () => { type Props = CommonProps & ConditionalProps - const Comp = defineComponent({ + const Comp = defineComponent({ __typeProps: {} as Props, }) // @ts-expect-error From 9d7984ef6314ca0043b82ca8e096fdc4fff4ff6f Mon Sep 17 00:00:00 2001 From: Evan You Date: Fri, 26 Apr 2024 19:59:02 +0800 Subject: [PATCH 3/6] feat(types): add __typeEmits for directly inferring emits from user types --- packages/dts-test/defineComponent.test-d.tsx | 99 +++++++++++++++++++ .../runtime-core/src/apiDefineComponent.ts | 87 ++++------------ packages/runtime-core/src/apiSetupHelpers.ts | 36 +++++-- packages/runtime-core/src/componentEmits.ts | 50 +++++++--- packages/runtime-core/src/componentOptions.ts | 93 +++++------------ packages/shared/src/typeUtils.ts | 31 ++++++ 6 files changed, 240 insertions(+), 156 deletions(-) diff --git a/packages/dts-test/defineComponent.test-d.tsx b/packages/dts-test/defineComponent.test-d.tsx index 6fc5e9cc983..838f73992d8 100644 --- a/packages/dts-test/defineComponent.test-d.tsx +++ b/packages/dts-test/defineComponent.test-d.tsx @@ -1648,6 +1648,7 @@ describe('__typeProps backdoor for union type for conditional props', () => { ; // @ts-expect-error ; + ; const c = new Comp() // @ts-expect-error @@ -1656,3 +1657,101 @@ describe('__typeProps backdoor for union type for conditional props', () => { c.$props = { color: 'white', appearance: 'text' } c.$props = { color: 'white', appearance: 'outline' } }) + +describe('__typeEmits backdoor, 3.3+ object syntax', () => { + type Emits = { + change: [id: number] + update: [value: string] + } + + const Comp = defineComponent({ + __typeEmits: {} as Emits, + mounted() { + this.$props.onChange?.(123) + // @ts-expect-error + this.$props.onChange?.('123') + this.$props.onUpdate?.('foo') + // @ts-expect-error + this.$props.onUpdate?.(123) + + // @ts-expect-error + this.$emit('foo') + + this.$emit('change', 123) + // @ts-expect-error + this.$emit('change', '123') + + this.$emit('update', 'test') + // @ts-expect-error + this.$emit('update', 123) + }, + }) + + ; id.toFixed(2)} /> + ; id.toUpperCase()} /> + // @ts-expect-error + ; id.slice(1)} /> + // @ts-expect-error + ; id.toFixed(2)} /> + + const c = new Comp() + // @ts-expect-error + c.$emit('foo') + + c.$emit('change', 123) + // @ts-expect-error + c.$emit('change', '123') + + c.$emit('update', 'test') + // @ts-expect-error + c.$emit('update', 123) +}) + +describe('__typeEmits backdoor, call signature syntax', () => { + type Emits = { + (e: 'change', id: number): void + (e: 'update', value: string): void + } + + const Comp = defineComponent({ + __typeEmits: {} as Emits, + mounted() { + this.$props.onChange?.(123) + // @ts-expect-error + this.$props.onChange?.('123') + this.$props.onUpdate?.('foo') + // @ts-expect-error + this.$props.onUpdate?.(123) + + // @ts-expect-error + this.$emit('foo') + + this.$emit('change', 123) + // @ts-expect-error + this.$emit('change', '123') + + this.$emit('update', 'test') + // @ts-expect-error + this.$emit('update', 123) + }, + }) + + ; id.toFixed(2)} /> + ; id.toUpperCase()} /> + // @ts-expect-error + ; id.slice(1)} /> + // @ts-expect-error + ; id.toFixed(2)} /> + + const c = new Comp() + // @ts-expect-error + c.$emit('foo') + + c.$emit('change', 123) + // @ts-expect-error + c.$emit('change', '123') + + c.$emit('update', 'test') + // @ts-expect-error + c.$emit('update', 123) +}) diff --git a/packages/runtime-core/src/apiDefineComponent.ts b/packages/runtime-core/src/apiDefineComponent.ts index 5735cb803ff..459b97debb3 100644 --- a/packages/runtime-core/src/apiDefineComponent.ts +++ b/packages/runtime-core/src/apiDefineComponent.ts @@ -5,7 +5,6 @@ import type { ComponentOptionsMixin, ComponentOptionsWithArrayProps, ComponentOptionsWithObjectProps, - ComponentOptionsWithTypeProps, ComponentOptionsWithoutProps, ComponentProvideOptions, ComputedOptions, @@ -26,7 +25,11 @@ import type { ExtractDefaultPropTypes, ExtractPropTypes, } from './componentProps' -import type { EmitsOptions, EmitsToProps } from './componentEmits' +import type { + EmitsOptions, + EmitsToProps, + TypeEmitsToOptions, +} from './componentEmits' import { extend, isFunction } from '@vue/shared' import type { VNodeProps } from './vnode' import type { @@ -35,6 +38,7 @@ import type { } from './componentPublicInstance' import type { SlotsType } from './componentSlots' import type { Directive } from './directives' +import type { TypeEmits } from './apiSetupHelpers' export type PublicProps = VNodeProps & AllowedComponentProps & @@ -171,7 +175,7 @@ export function defineComponent< }, ): DefineSetupFnComponent -// overload 2: object format with internal type props +// overload 2: object format no props or internal type props // backdoor for Vue Language Service export function defineComponent< Props = {}, @@ -190,8 +194,12 @@ export function defineComponent< Directives extends Record = {}, Exposed extends string = string, Provide extends ComponentProvideOptions = ComponentProvideOptions, + TE extends TypeEmits = {}, + ResolvedEmits extends EmitsOptions = {} extends E + ? TypeEmitsToOptions + : E, >( - options: ComponentOptionsWithTypeProps< + options: ComponentOptionsWithoutProps< Props, RawBindings, D, @@ -207,7 +215,9 @@ export function defineComponent< LC, Directives, Exposed, - Provide + Provide, + TE, + ResolvedEmits >, ): DefineComponent< Props, @@ -217,10 +227,10 @@ export function defineComponent< M, Mixin, Extends, - E, + ResolvedEmits, EE, PublicProps, - ResolveProps, + ResolveProps, ExtractDefaultPropTypes, S, LC, @@ -230,66 +240,7 @@ export function defineComponent< false > -// overload 3: object format with no props -// (uses user defined props interface) -// return type is for language-tools and TSX support -export function defineComponent< - Props = {}, - RawBindings = {}, - D = {}, - C extends ComputedOptions = {}, - M extends MethodOptions = {}, - Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, - Extends extends ComponentOptionsMixin = ComponentOptionsMixin, - E extends EmitsOptions = {}, - EE extends string = string, - I extends ComponentInjectOptions = {}, - II extends string = string, - S extends SlotsType = {}, - LC extends Record = {}, - Directives extends Record = {}, - Exposed extends string = string, - Provide extends ComponentProvideOptions = ComponentProvideOptions, ->( - options: ComponentOptionsWithoutProps< - Props, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - EE, - I, - II, - S, - LC, - Directives, - Exposed, - Provide - >, -): DefineComponent< - Props, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - EE, - PublicProps, - ResolveProps, - ExtractDefaultPropTypes, - S, - LC, - Directives, - Exposed, - Provide -> - -// overload 4: object format with array props declaration +// overload 3: object format with array props declaration // props inferred as { [key in PropNames]?: any } // return type is for language-tools and TSX support export function defineComponent< @@ -349,7 +300,7 @@ export function defineComponent< Provide > -// overload 5: object format with object props declaration +// overload 4: object format with object props declaration // see `ExtractPropTypes` in ./componentProps.ts export function defineComponent< // the Readonly constraint allows TS to treat the type of { required: true } diff --git a/packages/runtime-core/src/apiSetupHelpers.ts b/packages/runtime-core/src/apiSetupHelpers.ts index 382bb30b365..34718622000 100644 --- a/packages/runtime-core/src/apiSetupHelpers.ts +++ b/packages/runtime-core/src/apiSetupHelpers.ts @@ -16,8 +16,8 @@ import { } from './component' import type { EmitFn, EmitsOptions, ObjectEmitsOptions } from './componentEmits' import type { + ComponentOptionsBase, ComponentOptionsMixin, - ComponentOptionsWithoutProps, ComputedOptions, MethodOptions, } from './componentOptions' @@ -135,9 +135,11 @@ export function defineEmits( export function defineEmits( emitOptions: E, ): EmitFn -export function defineEmits< - T extends ((...args: any[]) => any) | Record, ->(): T extends (...args: any[]) => any ? T : ShortEmits +export function defineEmits(): T extends ( + ...args: any[] +) => any + ? T + : ShortEmits // implementation export function defineEmits() { if (__DEV__) { @@ -146,6 +148,8 @@ export function defineEmits() { return null as any } +export type TypeEmits = ((...args: any[]) => any) | Record + type RecordToUnion> = T[keyof T] type ShortEmits> = UnionToIntersection< @@ -191,15 +195,33 @@ export function defineOptions< Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, Extends extends ComponentOptionsMixin = ComponentOptionsMixin, >( - options?: ComponentOptionsWithoutProps< + options?: ComponentOptionsBase< {}, RawBindings, D, C, M, Mixin, - Extends - > & { emits?: undefined; expose?: undefined; slots?: undefined }, + Extends, + {} + > & { + /** + * props should be defined via defineProps(). + */ + props: never + /** + * emits should be defined via defineEmits(). + */ + emits?: never + /** + * expose should be defined via defineExpose(). + */ + expose?: never + /** + * slots should be defined via defineSlots(). + */ + slots?: never + }, ): void { if (__DEV__) { warnRuntimeUsage(`defineOptions`) diff --git a/packages/runtime-core/src/componentEmits.ts b/packages/runtime-core/src/componentEmits.ts index 4551235bc5a..ef264252dba 100644 --- a/packages/runtime-core/src/componentEmits.ts +++ b/packages/runtime-core/src/componentEmits.ts @@ -1,5 +1,6 @@ import { EMPTY_OBJ, + type OverloadParameters, type UnionToIntersection, camelize, extend, @@ -28,6 +29,7 @@ import { compatModelEmit, compatModelEventPrefix, } from './compat/componentVModel' +import type { TypeEmits } from './apiSetupHelpers' export type ObjectEmitsOptions = Record< string, @@ -36,23 +38,41 @@ export type ObjectEmitsOptions = Record< export type EmitsOptions = ObjectEmitsOptions | string[] -export type EmitsToProps = T extends string[] - ? { - [K in `on${Capitalize}`]?: (...args: any[]) => any - } - : T extends ObjectEmitsOptions +export type EmitsToProps = + T extends string[] ? { - [K in `on${Capitalize}`]?: K extends `on${infer C}` - ? ( - ...args: T[Uncapitalize] extends (...args: infer P) => any - ? P - : T[Uncapitalize] extends null - ? any[] - : never - ) => any - : never + [K in `on${Capitalize}`]?: (...args: any[]) => any } - : {} + : T extends ObjectEmitsOptions + ? { + [K in `on${Capitalize}`]?: K extends `on${infer C}` + ? ( + ...args: T[Uncapitalize] extends (...args: infer P) => any + ? P + : T[Uncapitalize] extends null + ? any[] + : never + ) => any + : never + } + : {} + +export type TypeEmitsToOptions = + T extends Record + ? { + [K in keyof T]: T[K] extends [...args: infer Args] + ? (...args: Args) => any + : () => any + } + : T extends (...args: any[]) => any + ? ParametersToFns> + : {} + +type ParametersToFns = { + [K in T[0]]: K extends `${infer C}` + ? (...args: T extends [C, ...infer Args] ? Args : never) => any + : never +} export type ShortEmitsToObject = E extends Record diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index 64c15b5fe1c..d10d2a850b3 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -54,7 +54,11 @@ import type { ExtractDefaultPropTypes, ExtractPropTypes, } from './componentProps' -import type { EmitsOptions, EmitsToProps } from './componentEmits' +import type { + EmitsOptions, + EmitsToProps, + TypeEmitsToOptions, +} from './componentEmits' import type { Directive } from './directives' import { type ComponentPublicInstance, @@ -76,7 +80,7 @@ import { import type { OptionMergeFunction } from './apiCreateApp' import { LifecycleHooks } from './enums' import type { SlotsType } from './componentSlots' -import { normalizePropsOrEmits } from './apiSetupHelpers' +import { type TypeEmits, normalizePropsOrEmits } from './apiSetupHelpers' /** * Interface for declaring custom options. @@ -218,65 +222,10 @@ export interface RuntimeCompilerOptions { delimiters?: [string, string] } -export type ComponentOptionsWithTypeProps< - Props = {}, - RawBindings = {}, - D = {}, - C extends ComputedOptions = {}, - M extends MethodOptions = {}, - Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, - Extends extends ComponentOptionsMixin = ComponentOptionsMixin, - E extends EmitsOptions = EmitsOptions, - EE extends string = string, - I extends ComponentInjectOptions = {}, - II extends string = string, - S extends SlotsType = {}, - LC extends Record = {}, - Directives extends Record = {}, - Exposed extends string = string, - Provide extends ComponentProvideOptions = ComponentProvideOptions, - PE = Props & EmitsToProps, -> = ComponentOptionsBase< - PE, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - EE, - {}, - I, - II, - S, - LC, - Directives, - Exposed, - Provide -> & { - __typeProps: Props -} & ThisType< - CreateComponentPublicInstance< - PE, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - EE, - {}, - false, - I, - S, - LC, - Directives, - Exposed - > - > - +/** + * This is named "without props" but also handles the case of direct type + * inference using internal __typeProps and __typeEmits options. + */ export type ComponentOptionsWithoutProps< Props = {}, RawBindings = {}, @@ -285,7 +234,7 @@ export type ComponentOptionsWithoutProps< M extends MethodOptions = {}, Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, Extends extends ComponentOptionsMixin = ComponentOptionsMixin, - E extends EmitsOptions = EmitsOptions, + E extends EmitsOptions = {}, EE extends string = string, I extends ComponentInjectOptions = {}, II extends string = string, @@ -294,7 +243,11 @@ export type ComponentOptionsWithoutProps< Directives extends Record = {}, Exposed extends string = string, Provide extends ComponentProvideOptions = ComponentProvideOptions, - PE = Props & EmitsToProps, + TE extends TypeEmits = {}, + ResolvedEmits extends EmitsOptions = {} extends E + ? TypeEmitsToOptions + : E, + PE = Props & EmitsToProps, > = ComponentOptionsBase< PE, RawBindings, @@ -314,7 +267,15 @@ export type ComponentOptionsWithoutProps< Exposed, Provide > & { - props?: undefined + props?: never + /** + * @private for language-tools use only + */ + __typeProps?: Props + /** + * @private for language-tools use only + */ + __typeEmits?: TE } & ThisType< CreateComponentPublicInstance< PE, @@ -324,8 +285,8 @@ export type ComponentOptionsWithoutProps< M, Mixin, Extends, - E, - PE, + ResolvedEmits, + EE, {}, false, I, diff --git a/packages/shared/src/typeUtils.ts b/packages/shared/src/typeUtils.ts index 63372d82916..7602b80a907 100644 --- a/packages/shared/src/typeUtils.ts +++ b/packages/shared/src/typeUtils.ts @@ -21,3 +21,34 @@ export type Awaited = T extends null | undefined ? Awaited // recursively unwrap the value : never // the argument to `then` was not callable : T // non-object or non-thenable + +/** + * Utility for extracting the paramteres from a function overload (for typed emits) + * https://github.com/microsoft/TypeScript/issues/32164#issuecomment-1146737709 + */ +export type OverloadParameters any> = Parameters< + OverloadUnion +> + +type OverloadProps = Pick + +type OverloadUnionRecursive< + TOverload, + TPartialOverload = unknown, +> = TOverload extends (...args: infer TArgs) => infer TReturn + ? TPartialOverload extends TOverload + ? never + : + | OverloadUnionRecursive< + TPartialOverload & TOverload, + TPartialOverload & + ((...args: TArgs) => TReturn) & + OverloadProps + > + | ((...args: TArgs) => TReturn) + : never + +type OverloadUnion any> = Exclude< + OverloadUnionRecursive<(() => never) & TOverload>, + TOverload extends () => never ? never : () => never +> From b2a6c5b95512156c7ebb6f34a1420cfb3a11451d Mon Sep 17 00:00:00 2001 From: Evan You Date: Sat, 27 Apr 2024 11:14:57 +0800 Subject: [PATCH 4/6] refactor: merge defineComponent overloads into a single signature --- packages/dts-test/defineComponent.test-d.tsx | 13 +- .../runtime-core/src/apiDefineComponent.ts | 273 +++++------- packages/runtime-core/src/apiSetupHelpers.ts | 24 +- packages/runtime-core/src/component.ts | 12 +- packages/runtime-core/src/componentEmits.ts | 8 +- packages/runtime-core/src/componentOptions.ts | 414 +++++++++--------- packages/runtime-core/src/componentProps.ts | 31 +- .../src/componentPublicInstance.ts | 6 +- packages/runtime-core/src/h.ts | 4 +- packages/runtime-core/src/index.ts | 10 +- .../__tests__/customElement.spec.ts | 8 +- packages/runtime-dom/src/apiCustomElement.ts | 166 ++++--- 12 files changed, 458 insertions(+), 511 deletions(-) diff --git a/packages/dts-test/defineComponent.test-d.tsx b/packages/dts-test/defineComponent.test-d.tsx index 838f73992d8..077f1abc075 100644 --- a/packages/dts-test/defineComponent.test-d.tsx +++ b/packages/dts-test/defineComponent.test-d.tsx @@ -15,7 +15,7 @@ import { withKeys, withModifiers, } from 'vue' -import { type IsUnion, describe, expectType } from './utils' +import { type IsAny, type IsUnion, describe, expectType } from './utils' describe('with object props', () => { interface ExpectedProps { @@ -1651,6 +1651,7 @@ describe('__typeProps backdoor for union type for conditional props', () => { ; const c = new Comp() + // @ts-expect-error c.$props = { color: 'white' } // @ts-expect-error @@ -1755,3 +1756,13 @@ describe('__typeEmits backdoor, call signature syntax', () => { // @ts-expect-error c.$emit('update', 123) }) + +defineComponent({ + props: { + foo: [String, null], + }, + setup(props) { + expectType>(false) + expectType(props.foo) + }, +}) diff --git a/packages/runtime-core/src/apiDefineComponent.ts b/packages/runtime-core/src/apiDefineComponent.ts index 459b97debb3..70b9d727c64 100644 --- a/packages/runtime-core/src/apiDefineComponent.ts +++ b/packages/runtime-core/src/apiDefineComponent.ts @@ -3,9 +3,6 @@ import type { ComponentOptions, ComponentOptionsBase, ComponentOptionsMixin, - ComponentOptionsWithArrayProps, - ComponentOptionsWithObjectProps, - ComponentOptionsWithoutProps, ComponentProvideOptions, ComputedOptions, MethodOptions, @@ -26,7 +23,7 @@ import type { ExtractPropTypes, } from './componentProps' import type { - EmitsOptions, + ComponentEmitsOptions, EmitsToProps, TypeEmitsToOptions, } from './componentEmits' @@ -38,13 +35,16 @@ import type { } from './componentPublicInstance' import type { SlotsType } from './componentSlots' import type { Directive } from './directives' -import type { TypeEmits } from './apiSetupHelpers' +import type { ComponentTypeEmits } from './apiSetupHelpers' export type PublicProps = VNodeProps & AllowedComponentProps & ComponentCustomProps -type ResolveProps = Readonly< +type ResolveProps< + PropsOrPropOptions, + E extends ComponentEmitsOptions, +> = Readonly< PropsOrPropOptions extends ComponentPropsOptions ? ExtractPropTypes : PropsOrPropOptions @@ -59,7 +59,7 @@ export type DefineComponent< M extends MethodOptions = MethodOptions, Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, Extends extends ComponentOptionsMixin = ComponentOptionsMixin, - E extends EmitsOptions = {}, + E extends ComponentEmitsOptions = {}, EE extends string = string, PP = PublicProps, Props = ResolveProps, @@ -113,7 +113,7 @@ export type DefineComponent< export type DefineSetupFnComponent< P extends Record, - E extends EmitsOptions = {}, + E extends ComponentEmitsOptions = {}, S extends SlotsType = SlotsType, Props = P & EmitsToProps, PP = PublicProps, @@ -144,7 +144,7 @@ export type DefineSetupFnComponent< // (uses user defined props interface) export function defineComponent< Props extends Record, - E extends EmitsOptions = {}, + E extends ComponentEmitsOptions = {}, EE extends string = string, S extends SlotsType = {}, >( @@ -160,7 +160,7 @@ export function defineComponent< ): DefineSetupFnComponent export function defineComponent< Props extends Record, - E extends EmitsOptions = {}, + E extends ComponentEmitsOptions = {}, EE extends string = string, S extends SlotsType = {}, >( @@ -175,189 +175,114 @@ export function defineComponent< }, ): DefineSetupFnComponent -// overload 2: object format no props or internal type props -// backdoor for Vue Language Service +// overload 2: defineComponent with options object, infer props from options export function defineComponent< - Props = {}, - RawBindings = {}, - D = {}, - C extends ComputedOptions = {}, - M extends MethodOptions = {}, + // props + TypeProps, + PropsOptions extends + ComponentObjectPropsOptions = ComponentObjectPropsOptions, + PropsKeys extends string = string, + // emits + TypeEmits extends ComponentTypeEmits = {}, + EmitsOptions extends ComponentEmitsOptions = {}, + EmitsKeys extends string = string, + // other options + Data = {}, + SetupBindings = {}, + Computed extends ComputedOptions = {}, + Methods extends MethodOptions = {}, Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, Extends extends ComponentOptionsMixin = ComponentOptionsMixin, - E extends EmitsOptions = {}, - EE extends string = string, - I extends ComponentInjectOptions = {}, - II extends string = string, - S extends SlotsType = {}, - LC extends Record = {}, + InjectOptions extends ComponentInjectOptions = {}, + InjectKeys extends string = string, + Slots extends SlotsType = {}, + LocalComponents extends Record = {}, Directives extends Record = {}, Exposed extends string = string, Provide extends ComponentProvideOptions = ComponentProvideOptions, - TE extends TypeEmits = {}, - ResolvedEmits extends EmitsOptions = {} extends E - ? TypeEmitsToOptions - : E, + // resolved types + ResolvedEmits extends ComponentEmitsOptions = {} extends EmitsOptions + ? TypeEmitsToOptions + : EmitsOptions, + InferredProps = unknown extends TypeProps + ? string extends PropsKeys + ? ComponentObjectPropsOptions extends PropsOptions + ? {} + : ExtractPropTypes + : { [key in PropsKeys]?: any } + : TypeProps, + ResolvedProps = Readonly>, >( - options: ComponentOptionsWithoutProps< - Props, - RawBindings, - D, - C, - M, + options: { + props?: (PropsOptions & ThisType) | PropsKeys[] + /** + * @private for language-tools use only + */ + __typeProps?: TypeProps + /** + * @private for language-tools use only + */ + __typeEmits?: TypeEmits + } & ComponentOptionsBase< + ResolvedProps, + SetupBindings, + Data, + Computed, + Methods, Mixin, Extends, - E, - EE, - I, - II, - S, - LC, - Directives, - Exposed, - Provide, - TE, - ResolvedEmits - >, -): DefineComponent< - Props, - RawBindings, - D, - C, - M, - Mixin, - Extends, - ResolvedEmits, - EE, - PublicProps, - ResolveProps, - ExtractDefaultPropTypes, - S, - LC, - Directives, - Exposed, - Provide, - false -> - -// overload 3: object format with array props declaration -// props inferred as { [key in PropNames]?: any } -// return type is for language-tools and TSX support -export function defineComponent< - PropNames extends string, - RawBindings, - D, - C extends ComputedOptions = {}, - M extends MethodOptions = {}, - Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, - Extends extends ComponentOptionsMixin = ComponentOptionsMixin, - E extends EmitsOptions = {}, - EE extends string = string, - S extends SlotsType = {}, - I extends ComponentInjectOptions = {}, - II extends string = string, - LC extends Record = {}, - Directives extends Record = {}, - Exposed extends string = string, - Provide extends ComponentProvideOptions = ComponentProvideOptions, - Props = Readonly<{ [key in PropNames]?: any }>, ->( - options: ComponentOptionsWithArrayProps< - PropNames, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - EE, - I, - II, - S, - LC, - Directives, - Exposed, - Provide - >, -): DefineComponent< - Props, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - EE, - PublicProps, - ResolveProps, - ExtractDefaultPropTypes, - S, - LC, - Directives, - Exposed, - Provide -> - -// overload 4: object format with object props declaration -// see `ExtractPropTypes` in ./componentProps.ts -export function defineComponent< - // the Readonly constraint allows TS to treat the type of { required: true } - // as constant instead of boolean. - PropsOptions extends Readonly, - RawBindings, - D, - C extends ComputedOptions = {}, - M extends MethodOptions = {}, - Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, - Extends extends ComponentOptionsMixin = ComponentOptionsMixin, - E extends EmitsOptions = {}, - EE extends string = string, - I extends ComponentInjectOptions = {}, - II extends string = string, - S extends SlotsType = {}, - LC extends Record = {}, - Directives extends Record = {}, - Exposed extends string = string, - Provide extends ComponentProvideOptions = ComponentProvideOptions, ->( - options: ComponentOptionsWithObjectProps< - PropsOptions, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - EE, - I, - II, - S, - LC, + EmitsOptions, + EmitsKeys, + {}, // Defaults + InjectOptions, + InjectKeys, + Slots, + LocalComponents, Directives, Exposed, Provide - >, + > & + ThisType< + CreateComponentPublicInstance< + ResolvedProps, + SetupBindings, + Data, + Computed, + Methods, + Mixin, + Extends, + ResolvedEmits, + EmitsKeys, + {}, + false, + InjectOptions, + Slots, + LocalComponents, + Directives, + Exposed + > + >, ): DefineComponent< - PropsOptions, - RawBindings, - D, - C, - M, + InferredProps, + SetupBindings, + Data, + Computed, + Methods, Mixin, Extends, - E, - EE, + ResolvedEmits, + EmitsKeys, PublicProps, - ResolveProps, + ResolvedProps, ExtractDefaultPropTypes, - S, - LC, + Slots, + LocalComponents, Directives, Exposed, - Provide + Provide, + // MakeDefaultsOptional - if TypeProps is provided, set to false to use + // user props types verbatim + unknown extends TypeProps ? true : false > // implementation, close to no-op diff --git a/packages/runtime-core/src/apiSetupHelpers.ts b/packages/runtime-core/src/apiSetupHelpers.ts index 34718622000..da092babcf5 100644 --- a/packages/runtime-core/src/apiSetupHelpers.ts +++ b/packages/runtime-core/src/apiSetupHelpers.ts @@ -14,7 +14,11 @@ import { setCurrentInstance, unsetCurrentInstance, } from './component' -import type { EmitFn, EmitsOptions, ObjectEmitsOptions } from './componentEmits' +import type { + ComponentEmitsOptions, + EmitFn, + ObjectEmitsOptions, +} from './componentEmits' import type { ComponentOptionsBase, ComponentOptionsMixin, @@ -132,10 +136,10 @@ type BooleanKey = K extends any export function defineEmits( emitOptions: EE[], ): EmitFn -export function defineEmits( - emitOptions: E, -): EmitFn -export function defineEmits(): T extends ( +export function defineEmits< + E extends ComponentEmitsOptions = ComponentEmitsOptions, +>(emitOptions: E): EmitFn +export function defineEmits(): T extends ( ...args: any[] ) => any ? T @@ -148,7 +152,9 @@ export function defineEmits() { return null as any } -export type TypeEmits = ((...args: any[]) => any) | Record +export type ComponentTypeEmits = + | ((...args: any[]) => any) + | Record type RecordToUnion> = T[keyof T] @@ -392,7 +398,7 @@ function getContext(): SetupContext { * @internal */ export function normalizePropsOrEmits( - props: ComponentPropsOptions | EmitsOptions, + props: ComponentPropsOptions | ComponentEmitsOptions, ) { return isArray(props) ? props.reduce( @@ -439,8 +445,8 @@ export function mergeDefaults( * @internal */ export function mergeModels( - a: ComponentPropsOptions | EmitsOptions, - b: ComponentPropsOptions | EmitsOptions, + a: ComponentPropsOptions | ComponentEmitsOptions, + b: ComponentPropsOptions | ComponentEmitsOptions, ) { if (!a || !b) return a || b if (isArray(a) && isArray(b)) return a.concat(b) diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index 68d908310d4..10317e5aff9 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -51,8 +51,8 @@ import { resolveMergedOptions, } from './componentOptions' import { + type ComponentEmitsOptions, type EmitFn, - type EmitsOptions, type EmitsToProps, type ObjectEmitsOptions, type ShortEmitsToObject, @@ -211,9 +211,9 @@ export interface ComponentInternalOptions { export interface FunctionalComponent< P = {}, - E extends EmitsOptions | Record = {}, + E extends ComponentEmitsOptions | Record = {}, S extends Record = any, - EE extends EmitsOptions = ShortEmitsToObject, + EE extends ComponentEmitsOptions = ShortEmitsToObject, > extends ComponentInternalOptions { // use of any here is intentional so it can be a valid JSX Element constructor ( @@ -245,7 +245,7 @@ export type ConcreteComponent< D = any, C extends ComputedOptions = ComputedOptions, M extends MethodOptions = MethodOptions, - E extends EmitsOptions | Record = {}, + E extends ComponentEmitsOptions | Record = {}, S extends Record = any, > = | ComponentOptions @@ -261,7 +261,7 @@ export type Component< D = any, C extends ComputedOptions = ComputedOptions, M extends MethodOptions = MethodOptions, - E extends EmitsOptions | Record = {}, + E extends ComponentEmitsOptions | Record = {}, S extends Record = any, > = | ConcreteComponent @@ -273,7 +273,7 @@ type LifecycleHook = TFn[] | null // use `E extends any` to force evaluating type to fix #2362 export type SetupContext< - E = EmitsOptions, + E = ComponentEmitsOptions, S extends SlotsType = {}, > = E extends any ? { diff --git a/packages/runtime-core/src/componentEmits.ts b/packages/runtime-core/src/componentEmits.ts index ef264252dba..fae4f6c9333 100644 --- a/packages/runtime-core/src/componentEmits.ts +++ b/packages/runtime-core/src/componentEmits.ts @@ -29,16 +29,16 @@ import { compatModelEmit, compatModelEventPrefix, } from './compat/componentVModel' -import type { TypeEmits } from './apiSetupHelpers' +import type { ComponentTypeEmits } from './apiSetupHelpers' export type ObjectEmitsOptions = Record< string, ((...args: any[]) => any) | null > -export type EmitsOptions = ObjectEmitsOptions | string[] +export type ComponentEmitsOptions = ObjectEmitsOptions | string[] -export type EmitsToProps = +export type EmitsToProps = T extends string[] ? { [K in `on${Capitalize}`]?: (...args: any[]) => any @@ -57,7 +57,7 @@ export type EmitsToProps = } : {} -export type TypeEmitsToOptions = +export type TypeEmitsToOptions = T extends Record ? { [K in keyof T]: T[K] extends [...args: infer Args] diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index d10d2a850b3..1246a2aa6ba 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -55,7 +55,7 @@ import type { ExtractPropTypes, } from './componentProps' import type { - EmitsOptions, + ComponentEmitsOptions, EmitsToProps, TypeEmitsToOptions, } from './componentEmits' @@ -80,7 +80,10 @@ import { import type { OptionMergeFunction } from './apiCreateApp' import { LifecycleHooks } from './enums' import type { SlotsType } from './componentSlots' -import { type TypeEmits, normalizePropsOrEmits } from './apiSetupHelpers' +import { + type ComponentTypeEmits, + normalizePropsOrEmits, +} from './apiSetupHelpers' /** * Interface for declaring custom options. @@ -110,7 +113,7 @@ export interface ComponentOptionsBase< M extends MethodOptions, Mixin extends ComponentOptionsMixin, Extends extends ComponentOptionsMixin, - E extends EmitsOptions, + E extends ComponentEmitsOptions, EE extends string = string, Defaults = {}, I extends ComponentInjectOptions = {}, @@ -222,199 +225,6 @@ export interface RuntimeCompilerOptions { delimiters?: [string, string] } -/** - * This is named "without props" but also handles the case of direct type - * inference using internal __typeProps and __typeEmits options. - */ -export type ComponentOptionsWithoutProps< - Props = {}, - RawBindings = {}, - D = {}, - C extends ComputedOptions = {}, - M extends MethodOptions = {}, - Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, - Extends extends ComponentOptionsMixin = ComponentOptionsMixin, - E extends EmitsOptions = {}, - EE extends string = string, - I extends ComponentInjectOptions = {}, - II extends string = string, - S extends SlotsType = {}, - LC extends Record = {}, - Directives extends Record = {}, - Exposed extends string = string, - Provide extends ComponentProvideOptions = ComponentProvideOptions, - TE extends TypeEmits = {}, - ResolvedEmits extends EmitsOptions = {} extends E - ? TypeEmitsToOptions - : E, - PE = Props & EmitsToProps, -> = ComponentOptionsBase< - PE, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - EE, - {}, - I, - II, - S, - LC, - Directives, - Exposed, - Provide -> & { - props?: never - /** - * @private for language-tools use only - */ - __typeProps?: Props - /** - * @private for language-tools use only - */ - __typeEmits?: TE -} & ThisType< - CreateComponentPublicInstance< - PE, - RawBindings, - D, - C, - M, - Mixin, - Extends, - ResolvedEmits, - EE, - {}, - false, - I, - S, - LC, - Directives, - Exposed - > - > - -export type ComponentOptionsWithArrayProps< - PropNames extends string = string, - RawBindings = {}, - D = {}, - C extends ComputedOptions = {}, - M extends MethodOptions = {}, - Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, - Extends extends ComponentOptionsMixin = ComponentOptionsMixin, - E extends EmitsOptions = EmitsOptions, - EE extends string = string, - I extends ComponentInjectOptions = {}, - II extends string = string, - S extends SlotsType = {}, - LC extends Record = {}, - Directives extends Record = {}, - Exposed extends string = string, - Provide extends ComponentProvideOptions = ComponentProvideOptions, - Props = Prettify>>, -> = ComponentOptionsBase< - Props, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - EE, - {}, - I, - II, - S, - LC, - Directives, - Exposed, - Provide -> & { - props: PropNames[] -} & ThisType< - CreateComponentPublicInstance< - Props, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - Props, - {}, - false, - I, - S, - LC, - Directives, - Exposed - > - > - -export type ComponentOptionsWithObjectProps< - PropsOptions = ComponentObjectPropsOptions, - RawBindings = {}, - D = {}, - C extends ComputedOptions = {}, - M extends MethodOptions = {}, - Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, - Extends extends ComponentOptionsMixin = ComponentOptionsMixin, - E extends EmitsOptions = EmitsOptions, - EE extends string = string, - I extends ComponentInjectOptions = {}, - II extends string = string, - S extends SlotsType = {}, - LC extends Record = {}, - Directives extends Record = {}, - Exposed extends string = string, - Provide extends ComponentProvideOptions = ComponentProvideOptions, - Props = Prettify & EmitsToProps>>, - Defaults = ExtractDefaultPropTypes, -> = ComponentOptionsBase< - Props, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - EE, - Defaults, - I, - II, - S, - LC, - Directives, - Exposed, - Provide -> & { - props: PropsOptions & ThisType -} & ThisType< - CreateComponentPublicInstance< - Props, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - Props, - Defaults, - false, - I, - S, - LC, - Directives - > - > - export type ComponentOptions< Props = {}, RawBindings = any, @@ -423,7 +233,7 @@ export type ComponentOptions< M extends MethodOptions = any, Mixin extends ComponentOptionsMixin = any, Extends extends ComponentOptionsMixin = any, - E extends EmitsOptions = any, + E extends ComponentEmitsOptions = any, EE extends string = string, Defaults = {}, I extends ComponentInjectOptions = {}, @@ -1221,16 +1031,16 @@ function mergeObjectOptions(to: Object | undefined, from: Object | undefined) { } function mergeEmitsOrPropsOptions( - to: EmitsOptions | undefined, - from: EmitsOptions | undefined, -): EmitsOptions | undefined + to: ComponentEmitsOptions | undefined, + from: ComponentEmitsOptions | undefined, +): ComponentEmitsOptions | undefined function mergeEmitsOrPropsOptions( to: ComponentPropsOptions | undefined, from: ComponentPropsOptions | undefined, ): ComponentPropsOptions | undefined function mergeEmitsOrPropsOptions( - to: ComponentPropsOptions | EmitsOptions | undefined, - from: ComponentPropsOptions | EmitsOptions | undefined, + to: ComponentPropsOptions | ComponentEmitsOptions | undefined, + from: ComponentPropsOptions | ComponentEmitsOptions | undefined, ) { if (to) { if (isArray(to) && isArray(from)) { @@ -1258,3 +1068,203 @@ function mergeWatchOptions( } return merged } + +// Deprecated legacy types, kept because they were previously exported --------- + +/** + * @deprecated + */ +export type ComponentOptionsWithoutProps< + Props = {}, + RawBindings = {}, + D = {}, + C extends ComputedOptions = {}, + M extends MethodOptions = {}, + Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, + Extends extends ComponentOptionsMixin = ComponentOptionsMixin, + E extends ComponentEmitsOptions = {}, + EE extends string = string, + I extends ComponentInjectOptions = {}, + II extends string = string, + S extends SlotsType = {}, + LC extends Record = {}, + Directives extends Record = {}, + Exposed extends string = string, + Provide extends ComponentProvideOptions = ComponentProvideOptions, + TE extends ComponentTypeEmits = {}, + ResolvedEmits extends ComponentEmitsOptions = {} extends E + ? TypeEmitsToOptions + : E, + PE = Props & EmitsToProps, +> = ComponentOptionsBase< + PE, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + EE, + {}, + I, + II, + S, + LC, + Directives, + Exposed, + Provide +> & { + props?: never + /** + * @private for language-tools use only + */ + __typeProps?: Props + /** + * @private for language-tools use only + */ + __typeEmits?: TE +} & ThisType< + CreateComponentPublicInstance< + PE, + RawBindings, + D, + C, + M, + Mixin, + Extends, + ResolvedEmits, + EE, + {}, + false, + I, + S, + LC, + Directives, + Exposed + > + > + +/** + * @deprecated + */ +export type ComponentOptionsWithArrayProps< + PropNames extends string = string, + RawBindings = {}, + D = {}, + C extends ComputedOptions = {}, + M extends MethodOptions = {}, + Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, + Extends extends ComponentOptionsMixin = ComponentOptionsMixin, + E extends ComponentEmitsOptions = ComponentEmitsOptions, + EE extends string = string, + I extends ComponentInjectOptions = {}, + II extends string = string, + S extends SlotsType = {}, + LC extends Record = {}, + Directives extends Record = {}, + Exposed extends string = string, + Provide extends ComponentProvideOptions = ComponentProvideOptions, + Props = Prettify>>, +> = ComponentOptionsBase< + Props, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + EE, + {}, + I, + II, + S, + LC, + Directives, + Exposed, + Provide +> & { + props: PropNames[] +} & ThisType< + CreateComponentPublicInstance< + Props, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + Props, + {}, + false, + I, + S, + LC, + Directives, + Exposed + > + > + +/** + * @deprecated + */ +export type ComponentOptionsWithObjectProps< + PropsOptions = ComponentObjectPropsOptions, + RawBindings = {}, + D = {}, + C extends ComputedOptions = {}, + M extends MethodOptions = {}, + Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, + Extends extends ComponentOptionsMixin = ComponentOptionsMixin, + E extends ComponentEmitsOptions = ComponentEmitsOptions, + EE extends string = string, + I extends ComponentInjectOptions = {}, + II extends string = string, + S extends SlotsType = {}, + LC extends Record = {}, + Directives extends Record = {}, + Exposed extends string = string, + Provide extends ComponentProvideOptions = ComponentProvideOptions, + Props = Prettify & EmitsToProps>>, + Defaults = ExtractDefaultPropTypes, +> = ComponentOptionsBase< + Props, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + EE, + Defaults, + I, + II, + S, + LC, + Directives, + Exposed, + Provide +> & { + props: PropsOptions & ThisType +} & ThisType< + CreateComponentPublicInstance< + Props, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + Props, + Defaults, + false, + I, + S, + LC, + Directives + > + > diff --git a/packages/runtime-core/src/componentProps.ts b/packages/runtime-core/src/componentProps.ts index 5a4292b6f36..597a1f1f285 100644 --- a/packages/runtime-core/src/componentProps.ts +++ b/packages/runtime-core/src/componentProps.ts @@ -67,7 +67,7 @@ export interface PropOptions { skipFactory?: boolean } -export type PropType = PropConstructor | PropConstructor[] +export type PropType = PropConstructor | (PropConstructor | null)[] type PropConstructor = | { new (...args: any[]): T & {} } @@ -107,8 +107,10 @@ type DefaultKeys = { : never }[keyof T] -type InferPropType = [T] extends [null] - ? any // null & true would fail to infer +type InferPropType = [T] extends [null] + ? NullAsAny extends true + ? any + : null : [T] extends [{ type: null | true }] ? any // As TS issue https://github.com/Microsoft/TypeScript/issues/14829 // somehow `ObjectConstructor` when inferred from { (): T } becomes `any` // `BooleanConstructor` when inferred from PropConstructor(with PropMethod) becomes `Boolean` : [T] extends [ObjectConstructor | { type: ObjectConstructor }] @@ -119,8 +121,8 @@ type InferPropType = [T] extends [null] ? Date : [T] extends [(infer U)[] | { type: (infer U)[] }] ? U extends DateConstructor - ? Date | InferPropType - : InferPropType + ? Date | InferPropType + : InferPropType : [T] extends [Prop] ? unknown extends V ? IfAny @@ -594,7 +596,7 @@ function validatePropName(key: string) { // use function string name to check type constructors // so that it works across vms / iframes. -function getType(ctor: Prop): string { +function getType(ctor: Prop | null): string { // Early return for null to avoid unnecessary computations if (ctor === null) { return 'null' @@ -614,7 +616,7 @@ function getType(ctor: Prop): string { return '' } -function isSameType(a: Prop, b: Prop): boolean { +function isSameType(a: Prop | null, b: Prop | null): boolean { return getType(a) === getType(b) } @@ -707,24 +709,27 @@ type AssertionResult = { /** * dev only */ -function assertType(value: unknown, type: PropConstructor): AssertionResult { +function assertType( + value: unknown, + type: PropConstructor | null, +): AssertionResult { let valid const expectedType = getType(type) - if (isSimpleType(expectedType)) { + if (expectedType === 'null') { + valid = value === null + } else if (isSimpleType(expectedType)) { const t = typeof value valid = t === expectedType.toLowerCase() // for primitive wrapper objects if (!valid && t === 'object') { - valid = value instanceof type + valid = value instanceof (type as PropConstructor) } } else if (expectedType === 'Object') { valid = isObject(value) } else if (expectedType === 'Array') { valid = isArray(value) - } else if (expectedType === 'null') { - valid = value === null } else { - valid = value instanceof type + valid = value instanceof (type as PropConstructor) } return { valid, diff --git a/packages/runtime-core/src/componentPublicInstance.ts b/packages/runtime-core/src/componentPublicInstance.ts index 864b9786efe..9018f7a55b5 100644 --- a/packages/runtime-core/src/componentPublicInstance.ts +++ b/packages/runtime-core/src/componentPublicInstance.ts @@ -47,7 +47,7 @@ import { resolveMergedOptions, shouldCacheAccess, } from './componentOptions' -import type { EmitFn, EmitsOptions } from './componentEmits' +import type { ComponentEmitsOptions, EmitFn } from './componentEmits' import type { SlotsType, UnwrapSlotsType } from './componentSlots' import { markAttrsAccessed } from './componentRenderUtils' import { currentRenderingInstance } from './componentRenderContext' @@ -158,7 +158,7 @@ export type CreateComponentPublicInstance< M extends MethodOptions = {}, Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, Extends extends ComponentOptionsMixin = ComponentOptionsMixin, - E extends EmitsOptions = {}, + E extends ComponentEmitsOptions = {}, PublicProps = P, Defaults = {}, MakeDefaultsOptional extends boolean = false, @@ -225,7 +225,7 @@ export type ComponentPublicInstance< D = {}, // return from data() C extends ComputedOptions = {}, M extends MethodOptions = {}, - E extends EmitsOptions = {}, + E extends ComponentEmitsOptions = {}, PublicProps = P, Defaults = {}, MakeDefaultsOptional extends boolean = false, diff --git a/packages/runtime-core/src/h.ts b/packages/runtime-core/src/h.ts index 93e7fd9bc88..644620275fd 100644 --- a/packages/runtime-core/src/h.ts +++ b/packages/runtime-core/src/h.ts @@ -18,7 +18,7 @@ import type { ConcreteComponent, FunctionalComponent, } from './component' -import type { EmitsOptions } from './componentEmits' +import type { ComponentEmitsOptions } from './componentEmits' import type { DefineComponent } from './apiDefineComponent' // `h` is a more user-friendly version of `createVNode` that allows omitting the @@ -139,7 +139,7 @@ export function h( // functional component export function h< P, - E extends EmitsOptions = {}, + E extends ComponentEmitsOptions = {}, S extends Record = any, >( type: FunctionalComponent, diff --git a/packages/runtime-core/src/index.ts b/packages/runtime-core/src/index.ts index 5d36407ba6a..478ae6bbb56 100644 --- a/packages/runtime-core/src/index.ts +++ b/packages/runtime-core/src/index.ts @@ -76,6 +76,7 @@ export { withDefaults, type DefineProps, type ModelRef, + type ComponentTypeEmits, } from './apiSetupHelpers' /** @@ -260,9 +261,6 @@ export type { export type { ComponentOptions, ComponentOptionsMixin, - ComponentOptionsWithoutProps, - ComponentOptionsWithObjectProps, - ComponentOptionsWithArrayProps, ComponentCustomOptions, ComponentOptionsBase, ComponentProvideOptions, @@ -272,7 +270,11 @@ export type { RuntimeCompilerOptions, ComponentInjectOptions, } from './componentOptions' -export type { EmitsOptions, ObjectEmitsOptions } from './componentEmits' +export type { + ComponentEmitsOptions as EmitsOptions, + ObjectEmitsOptions, + EmitsToProps, +} from './componentEmits' export type { ComponentPublicInstance, ComponentCustomProperties, diff --git a/packages/runtime-dom/__tests__/customElement.spec.ts b/packages/runtime-dom/__tests__/customElement.spec.ts index fb746f72c4a..cc56de2d685 100644 --- a/packages/runtime-dom/__tests__/customElement.spec.ts +++ b/packages/runtime-dom/__tests__/customElement.spec.ts @@ -88,10 +88,14 @@ describe('defineCustomElement', () => { describe('props', () => { const E = defineCustomElement({ - props: ['foo', 'bar', 'bazQux'], + props: { + foo: [String, null], + bar: Object, + bazQux: null, + }, render() { return [ - h('div', null, this.foo), + h('div', null, this.foo || ''), h('div', null, this.bazQux || (this.bar && this.bar.x)), ] }, diff --git a/packages/runtime-dom/src/apiCustomElement.ts b/packages/runtime-dom/src/apiCustomElement.ts index 01ce2bad464..b8adc761b37 100644 --- a/packages/runtime-dom/src/apiCustomElement.ts +++ b/packages/runtime-dom/src/apiCustomElement.ts @@ -1,16 +1,19 @@ import { + type Component, + type EmitsOptions as ComponentEmitsOptions, type ComponentInjectOptions, type ComponentInternalInstance, + type ComponentObjectPropsOptions, type ComponentOptions, + type ComponentOptionsBase, type ComponentOptionsMixin, - type ComponentOptionsWithArrayProps, - type ComponentOptionsWithObjectProps, - type ComponentOptionsWithoutProps, - type ComponentPropsOptions, + type ComponentProvideOptions, type ComputedOptions, type ConcreteComponent, + type CreateComponentPublicInstance, type DefineComponent, - type EmitsOptions, + type Directive, + type EmitsToProps, type ExtractPropTypes, type MethodOptions, type RenderFunction, @@ -41,98 +44,79 @@ export function defineCustomElement( ) => RawBindings | RenderFunction, ): VueElementConstructor -// overload 2: object format with no props +// overload 2: defineCustomElement with options object, infer props from options export function defineCustomElement< - Props = {}, - RawBindings = {}, - D = {}, - C extends ComputedOptions = {}, - M extends MethodOptions = {}, + // props + PropsOptions extends + ComponentObjectPropsOptions = ComponentObjectPropsOptions, + PropsKeys extends string = string, + // emits + EmitsOptions extends ComponentEmitsOptions = {}, + EmitsKeys extends string = string, + // other options + Data = {}, + SetupBindings = {}, + Computed extends ComputedOptions = {}, + Methods extends MethodOptions = {}, Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, Extends extends ComponentOptionsMixin = ComponentOptionsMixin, - E extends EmitsOptions = EmitsOptions, - EE extends string = string, - I extends ComponentInjectOptions = {}, - II extends string = string, - S extends SlotsType = {}, + InjectOptions extends ComponentInjectOptions = {}, + InjectKeys extends string = string, + Slots extends SlotsType = {}, + LocalComponents extends Record = {}, + Directives extends Record = {}, + Exposed extends string = string, + Provide extends ComponentProvideOptions = ComponentProvideOptions, + // resolved types + InferredProps = string extends PropsKeys + ? ComponentObjectPropsOptions extends PropsOptions + ? {} + : ExtractPropTypes + : { [key in PropsKeys]?: any }, + ResolvedProps = InferredProps & EmitsToProps, >( - options: ComponentOptionsWithoutProps< - Props, - RawBindings, - D, - C, - M, + options: { + props?: (PropsOptions & ThisType) | PropsKeys[] + } & ComponentOptionsBase< + ResolvedProps, + SetupBindings, + Data, + Computed, + Methods, Mixin, Extends, - E, - EE, - I, - II, - S - > & { styles?: string[] }, -): VueElementConstructor - -// overload 3: object format with array props declaration -export function defineCustomElement< - PropNames extends string, - RawBindings, - D, - C extends ComputedOptions = {}, - M extends MethodOptions = {}, - Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, - Extends extends ComponentOptionsMixin = ComponentOptionsMixin, - E extends EmitsOptions = Record, - EE extends string = string, - I extends ComponentInjectOptions = {}, - II extends string = string, - S extends SlotsType = {}, ->( - options: ComponentOptionsWithArrayProps< - PropNames, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - EE, - I, - II, - S - > & { styles?: string[] }, -): VueElementConstructor<{ [K in PropNames]: any }> - -// overload 4: object format with object props declaration -export function defineCustomElement< - PropsOptions extends Readonly, - RawBindings, - D, - C extends ComputedOptions = {}, - M extends MethodOptions = {}, - Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, - Extends extends ComponentOptionsMixin = ComponentOptionsMixin, - E extends EmitsOptions = Record, - EE extends string = string, - I extends ComponentInjectOptions = {}, - II extends string = string, - S extends SlotsType = {}, ->( - options: ComponentOptionsWithObjectProps< - PropsOptions, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - EE, - I, - II, - S - > & { styles?: string[] }, -): VueElementConstructor> + EmitsOptions, + EmitsKeys, + {}, // Defaults + InjectOptions, + InjectKeys, + Slots, + LocalComponents, + Directives, + Exposed, + Provide + > & + ThisType< + CreateComponentPublicInstance< + Readonly, + SetupBindings, + Data, + Computed, + Methods, + Mixin, + Extends, + EmitsOptions, + EmitsKeys, + {}, + false, + InjectOptions, + Slots, + LocalComponents, + Directives, + Exposed + > + >, +): VueElementConstructor // overload 5: defining a custom element from the returned value of // `defineComponent` From 169ebfe4d2d57d42d140b041d7a722b9bb5d01ee Mon Sep 17 00:00:00 2001 From: Evan You Date: Sat, 27 Apr 2024 11:24:24 +0800 Subject: [PATCH 5/6] chore: fix EmitsOptions --- .../runtime-core/src/apiDefineComponent.ts | 47 +++++++++---------- packages/runtime-core/src/apiSetupHelpers.ts | 18 +++---- packages/runtime-core/src/component.ts | 12 ++--- packages/runtime-core/src/componentEmits.ts | 4 +- packages/runtime-core/src/componentOptions.ts | 24 +++++----- .../src/componentPublicInstance.ts | 6 +-- packages/runtime-core/src/h.ts | 4 +- packages/runtime-core/src/index.ts | 2 +- packages/runtime-dom/src/apiCustomElement.ts | 18 +++---- 9 files changed, 64 insertions(+), 71 deletions(-) diff --git a/packages/runtime-core/src/apiDefineComponent.ts b/packages/runtime-core/src/apiDefineComponent.ts index 70b9d727c64..7fce96586da 100644 --- a/packages/runtime-core/src/apiDefineComponent.ts +++ b/packages/runtime-core/src/apiDefineComponent.ts @@ -23,7 +23,7 @@ import type { ExtractPropTypes, } from './componentProps' import type { - ComponentEmitsOptions, + EmitsOptions, EmitsToProps, TypeEmitsToOptions, } from './componentEmits' @@ -41,10 +41,7 @@ export type PublicProps = VNodeProps & AllowedComponentProps & ComponentCustomProps -type ResolveProps< - PropsOrPropOptions, - E extends ComponentEmitsOptions, -> = Readonly< +type ResolveProps = Readonly< PropsOrPropOptions extends ComponentPropsOptions ? ExtractPropTypes : PropsOrPropOptions @@ -59,7 +56,7 @@ export type DefineComponent< M extends MethodOptions = MethodOptions, Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, Extends extends ComponentOptionsMixin = ComponentOptionsMixin, - E extends ComponentEmitsOptions = {}, + E extends EmitsOptions = {}, EE extends string = string, PP = PublicProps, Props = ResolveProps, @@ -113,7 +110,7 @@ export type DefineComponent< export type DefineSetupFnComponent< P extends Record, - E extends ComponentEmitsOptions = {}, + E extends EmitsOptions = {}, S extends SlotsType = SlotsType, Props = P & EmitsToProps, PP = PublicProps, @@ -144,7 +141,7 @@ export type DefineSetupFnComponent< // (uses user defined props interface) export function defineComponent< Props extends Record, - E extends ComponentEmitsOptions = {}, + E extends EmitsOptions = {}, EE extends string = string, S extends SlotsType = {}, >( @@ -160,7 +157,7 @@ export function defineComponent< ): DefineSetupFnComponent export function defineComponent< Props extends Record, - E extends ComponentEmitsOptions = {}, + E extends EmitsOptions = {}, EE extends string = string, S extends SlotsType = {}, >( @@ -179,13 +176,13 @@ export function defineComponent< export function defineComponent< // props TypeProps, - PropsOptions extends + RuntimePropsOptions extends ComponentObjectPropsOptions = ComponentObjectPropsOptions, - PropsKeys extends string = string, + RuntimePropsKeys extends string = string, // emits TypeEmits extends ComponentTypeEmits = {}, - EmitsOptions extends ComponentEmitsOptions = {}, - EmitsKeys extends string = string, + RuntimeEmitsOptions extends EmitsOptions = {}, + RuntimeEmitsKeys extends string = string, // other options Data = {}, SetupBindings = {}, @@ -201,20 +198,20 @@ export function defineComponent< Exposed extends string = string, Provide extends ComponentProvideOptions = ComponentProvideOptions, // resolved types - ResolvedEmits extends ComponentEmitsOptions = {} extends EmitsOptions + ResolvedEmits extends EmitsOptions = {} extends RuntimeEmitsOptions ? TypeEmitsToOptions - : EmitsOptions, + : RuntimeEmitsOptions, InferredProps = unknown extends TypeProps - ? string extends PropsKeys - ? ComponentObjectPropsOptions extends PropsOptions + ? string extends RuntimePropsKeys + ? ComponentObjectPropsOptions extends RuntimePropsOptions ? {} - : ExtractPropTypes - : { [key in PropsKeys]?: any } + : ExtractPropTypes + : { [key in RuntimePropsKeys]?: any } : TypeProps, ResolvedProps = Readonly>, >( options: { - props?: (PropsOptions & ThisType) | PropsKeys[] + props?: (RuntimePropsOptions & ThisType) | RuntimePropsKeys[] /** * @private for language-tools use only */ @@ -231,8 +228,8 @@ export function defineComponent< Methods, Mixin, Extends, - EmitsOptions, - EmitsKeys, + RuntimeEmitsOptions, + RuntimeEmitsKeys, {}, // Defaults InjectOptions, InjectKeys, @@ -252,7 +249,7 @@ export function defineComponent< Mixin, Extends, ResolvedEmits, - EmitsKeys, + RuntimeEmitsKeys, {}, false, InjectOptions, @@ -271,10 +268,10 @@ export function defineComponent< Mixin, Extends, ResolvedEmits, - EmitsKeys, + RuntimeEmitsKeys, PublicProps, ResolvedProps, - ExtractDefaultPropTypes, + ExtractDefaultPropTypes, Slots, LocalComponents, Directives, diff --git a/packages/runtime-core/src/apiSetupHelpers.ts b/packages/runtime-core/src/apiSetupHelpers.ts index da092babcf5..dbe27dde48e 100644 --- a/packages/runtime-core/src/apiSetupHelpers.ts +++ b/packages/runtime-core/src/apiSetupHelpers.ts @@ -14,11 +14,7 @@ import { setCurrentInstance, unsetCurrentInstance, } from './component' -import type { - ComponentEmitsOptions, - EmitFn, - ObjectEmitsOptions, -} from './componentEmits' +import type { EmitFn, EmitsOptions, ObjectEmitsOptions } from './componentEmits' import type { ComponentOptionsBase, ComponentOptionsMixin, @@ -136,9 +132,9 @@ type BooleanKey = K extends any export function defineEmits( emitOptions: EE[], ): EmitFn -export function defineEmits< - E extends ComponentEmitsOptions = ComponentEmitsOptions, ->(emitOptions: E): EmitFn +export function defineEmits( + emitOptions: E, +): EmitFn export function defineEmits(): T extends ( ...args: any[] ) => any @@ -398,7 +394,7 @@ function getContext(): SetupContext { * @internal */ export function normalizePropsOrEmits( - props: ComponentPropsOptions | ComponentEmitsOptions, + props: ComponentPropsOptions | EmitsOptions, ) { return isArray(props) ? props.reduce( @@ -445,8 +441,8 @@ export function mergeDefaults( * @internal */ export function mergeModels( - a: ComponentPropsOptions | ComponentEmitsOptions, - b: ComponentPropsOptions | ComponentEmitsOptions, + a: ComponentPropsOptions | EmitsOptions, + b: ComponentPropsOptions | EmitsOptions, ) { if (!a || !b) return a || b if (isArray(a) && isArray(b)) return a.concat(b) diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index 10317e5aff9..68d908310d4 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -51,8 +51,8 @@ import { resolveMergedOptions, } from './componentOptions' import { - type ComponentEmitsOptions, type EmitFn, + type EmitsOptions, type EmitsToProps, type ObjectEmitsOptions, type ShortEmitsToObject, @@ -211,9 +211,9 @@ export interface ComponentInternalOptions { export interface FunctionalComponent< P = {}, - E extends ComponentEmitsOptions | Record = {}, + E extends EmitsOptions | Record = {}, S extends Record = any, - EE extends ComponentEmitsOptions = ShortEmitsToObject, + EE extends EmitsOptions = ShortEmitsToObject, > extends ComponentInternalOptions { // use of any here is intentional so it can be a valid JSX Element constructor ( @@ -245,7 +245,7 @@ export type ConcreteComponent< D = any, C extends ComputedOptions = ComputedOptions, M extends MethodOptions = MethodOptions, - E extends ComponentEmitsOptions | Record = {}, + E extends EmitsOptions | Record = {}, S extends Record = any, > = | ComponentOptions @@ -261,7 +261,7 @@ export type Component< D = any, C extends ComputedOptions = ComputedOptions, M extends MethodOptions = MethodOptions, - E extends ComponentEmitsOptions | Record = {}, + E extends EmitsOptions | Record = {}, S extends Record = any, > = | ConcreteComponent @@ -273,7 +273,7 @@ type LifecycleHook = TFn[] | null // use `E extends any` to force evaluating type to fix #2362 export type SetupContext< - E = ComponentEmitsOptions, + E = EmitsOptions, S extends SlotsType = {}, > = E extends any ? { diff --git a/packages/runtime-core/src/componentEmits.ts b/packages/runtime-core/src/componentEmits.ts index fae4f6c9333..eb80d02afb6 100644 --- a/packages/runtime-core/src/componentEmits.ts +++ b/packages/runtime-core/src/componentEmits.ts @@ -36,9 +36,9 @@ export type ObjectEmitsOptions = Record< ((...args: any[]) => any) | null > -export type ComponentEmitsOptions = ObjectEmitsOptions | string[] +export type EmitsOptions = ObjectEmitsOptions | string[] -export type EmitsToProps = +export type EmitsToProps = T extends string[] ? { [K in `on${Capitalize}`]?: (...args: any[]) => any diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index 1246a2aa6ba..ac1841edee9 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -55,7 +55,7 @@ import type { ExtractPropTypes, } from './componentProps' import type { - ComponentEmitsOptions, + EmitsOptions, EmitsToProps, TypeEmitsToOptions, } from './componentEmits' @@ -113,7 +113,7 @@ export interface ComponentOptionsBase< M extends MethodOptions, Mixin extends ComponentOptionsMixin, Extends extends ComponentOptionsMixin, - E extends ComponentEmitsOptions, + E extends EmitsOptions, EE extends string = string, Defaults = {}, I extends ComponentInjectOptions = {}, @@ -233,7 +233,7 @@ export type ComponentOptions< M extends MethodOptions = any, Mixin extends ComponentOptionsMixin = any, Extends extends ComponentOptionsMixin = any, - E extends ComponentEmitsOptions = any, + E extends EmitsOptions = any, EE extends string = string, Defaults = {}, I extends ComponentInjectOptions = {}, @@ -1031,16 +1031,16 @@ function mergeObjectOptions(to: Object | undefined, from: Object | undefined) { } function mergeEmitsOrPropsOptions( - to: ComponentEmitsOptions | undefined, - from: ComponentEmitsOptions | undefined, -): ComponentEmitsOptions | undefined + to: EmitsOptions | undefined, + from: EmitsOptions | undefined, +): EmitsOptions | undefined function mergeEmitsOrPropsOptions( to: ComponentPropsOptions | undefined, from: ComponentPropsOptions | undefined, ): ComponentPropsOptions | undefined function mergeEmitsOrPropsOptions( - to: ComponentPropsOptions | ComponentEmitsOptions | undefined, - from: ComponentPropsOptions | ComponentEmitsOptions | undefined, + to: ComponentPropsOptions | EmitsOptions | undefined, + from: ComponentPropsOptions | EmitsOptions | undefined, ) { if (to) { if (isArray(to) && isArray(from)) { @@ -1082,7 +1082,7 @@ export type ComponentOptionsWithoutProps< M extends MethodOptions = {}, Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, Extends extends ComponentOptionsMixin = ComponentOptionsMixin, - E extends ComponentEmitsOptions = {}, + E extends EmitsOptions = {}, EE extends string = string, I extends ComponentInjectOptions = {}, II extends string = string, @@ -1092,7 +1092,7 @@ export type ComponentOptionsWithoutProps< Exposed extends string = string, Provide extends ComponentProvideOptions = ComponentProvideOptions, TE extends ComponentTypeEmits = {}, - ResolvedEmits extends ComponentEmitsOptions = {} extends E + ResolvedEmits extends EmitsOptions = {} extends E ? TypeEmitsToOptions : E, PE = Props & EmitsToProps, @@ -1156,7 +1156,7 @@ export type ComponentOptionsWithArrayProps< M extends MethodOptions = {}, Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, Extends extends ComponentOptionsMixin = ComponentOptionsMixin, - E extends ComponentEmitsOptions = ComponentEmitsOptions, + E extends EmitsOptions = EmitsOptions, EE extends string = string, I extends ComponentInjectOptions = {}, II extends string = string, @@ -1218,7 +1218,7 @@ export type ComponentOptionsWithObjectProps< M extends MethodOptions = {}, Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, Extends extends ComponentOptionsMixin = ComponentOptionsMixin, - E extends ComponentEmitsOptions = ComponentEmitsOptions, + E extends EmitsOptions = EmitsOptions, EE extends string = string, I extends ComponentInjectOptions = {}, II extends string = string, diff --git a/packages/runtime-core/src/componentPublicInstance.ts b/packages/runtime-core/src/componentPublicInstance.ts index 9018f7a55b5..864b9786efe 100644 --- a/packages/runtime-core/src/componentPublicInstance.ts +++ b/packages/runtime-core/src/componentPublicInstance.ts @@ -47,7 +47,7 @@ import { resolveMergedOptions, shouldCacheAccess, } from './componentOptions' -import type { ComponentEmitsOptions, EmitFn } from './componentEmits' +import type { EmitFn, EmitsOptions } from './componentEmits' import type { SlotsType, UnwrapSlotsType } from './componentSlots' import { markAttrsAccessed } from './componentRenderUtils' import { currentRenderingInstance } from './componentRenderContext' @@ -158,7 +158,7 @@ export type CreateComponentPublicInstance< M extends MethodOptions = {}, Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, Extends extends ComponentOptionsMixin = ComponentOptionsMixin, - E extends ComponentEmitsOptions = {}, + E extends EmitsOptions = {}, PublicProps = P, Defaults = {}, MakeDefaultsOptional extends boolean = false, @@ -225,7 +225,7 @@ export type ComponentPublicInstance< D = {}, // return from data() C extends ComputedOptions = {}, M extends MethodOptions = {}, - E extends ComponentEmitsOptions = {}, + E extends EmitsOptions = {}, PublicProps = P, Defaults = {}, MakeDefaultsOptional extends boolean = false, diff --git a/packages/runtime-core/src/h.ts b/packages/runtime-core/src/h.ts index 644620275fd..93e7fd9bc88 100644 --- a/packages/runtime-core/src/h.ts +++ b/packages/runtime-core/src/h.ts @@ -18,7 +18,7 @@ import type { ConcreteComponent, FunctionalComponent, } from './component' -import type { ComponentEmitsOptions } from './componentEmits' +import type { EmitsOptions } from './componentEmits' import type { DefineComponent } from './apiDefineComponent' // `h` is a more user-friendly version of `createVNode` that allows omitting the @@ -139,7 +139,7 @@ export function h( // functional component export function h< P, - E extends ComponentEmitsOptions = {}, + E extends EmitsOptions = {}, S extends Record = any, >( type: FunctionalComponent, diff --git a/packages/runtime-core/src/index.ts b/packages/runtime-core/src/index.ts index 478ae6bbb56..e4a9e53f29c 100644 --- a/packages/runtime-core/src/index.ts +++ b/packages/runtime-core/src/index.ts @@ -271,7 +271,7 @@ export type { ComponentInjectOptions, } from './componentOptions' export type { - ComponentEmitsOptions as EmitsOptions, + EmitsOptions, ObjectEmitsOptions, EmitsToProps, } from './componentEmits' diff --git a/packages/runtime-dom/src/apiCustomElement.ts b/packages/runtime-dom/src/apiCustomElement.ts index b8adc761b37..01728466241 100644 --- a/packages/runtime-dom/src/apiCustomElement.ts +++ b/packages/runtime-dom/src/apiCustomElement.ts @@ -1,6 +1,5 @@ import { type Component, - type EmitsOptions as ComponentEmitsOptions, type ComponentInjectOptions, type ComponentInternalInstance, type ComponentObjectPropsOptions, @@ -13,6 +12,7 @@ import { type CreateComponentPublicInstance, type DefineComponent, type Directive, + type EmitsOptions, type EmitsToProps, type ExtractPropTypes, type MethodOptions, @@ -47,11 +47,11 @@ export function defineCustomElement( // overload 2: defineCustomElement with options object, infer props from options export function defineCustomElement< // props - PropsOptions extends + RuntimePropsOptions extends ComponentObjectPropsOptions = ComponentObjectPropsOptions, PropsKeys extends string = string, // emits - EmitsOptions extends ComponentEmitsOptions = {}, + RuntimeEmitsOptions extends EmitsOptions = {}, EmitsKeys extends string = string, // other options Data = {}, @@ -69,14 +69,14 @@ export function defineCustomElement< Provide extends ComponentProvideOptions = ComponentProvideOptions, // resolved types InferredProps = string extends PropsKeys - ? ComponentObjectPropsOptions extends PropsOptions + ? ComponentObjectPropsOptions extends RuntimePropsOptions ? {} - : ExtractPropTypes + : ExtractPropTypes : { [key in PropsKeys]?: any }, - ResolvedProps = InferredProps & EmitsToProps, + ResolvedProps = InferredProps & EmitsToProps, >( options: { - props?: (PropsOptions & ThisType) | PropsKeys[] + props?: (RuntimePropsOptions & ThisType) | PropsKeys[] } & ComponentOptionsBase< ResolvedProps, SetupBindings, @@ -85,7 +85,7 @@ export function defineCustomElement< Methods, Mixin, Extends, - EmitsOptions, + RuntimeEmitsOptions, EmitsKeys, {}, // Defaults InjectOptions, @@ -105,7 +105,7 @@ export function defineCustomElement< Methods, Mixin, Extends, - EmitsOptions, + RuntimeEmitsOptions, EmitsKeys, {}, false, From 03f87a7323c6fc6f0b7a9b238b8e18fc6fff5655 Mon Sep 17 00:00:00 2001 From: Evan You Date: Sat, 27 Apr 2024 11:26:35 +0800 Subject: [PATCH 6/6] chore: typo --- packages/shared/src/typeUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shared/src/typeUtils.ts b/packages/shared/src/typeUtils.ts index 7602b80a907..4846751b84e 100644 --- a/packages/shared/src/typeUtils.ts +++ b/packages/shared/src/typeUtils.ts @@ -23,7 +23,7 @@ export type Awaited = T extends null | undefined : T // non-object or non-thenable /** - * Utility for extracting the paramteres from a function overload (for typed emits) + * Utility for extracting the parameters from a function overload (for typed emits) * https://github.com/microsoft/TypeScript/issues/32164#issuecomment-1146737709 */ export type OverloadParameters any> = Parameters<