diff --git a/packages/dts-test/setupHelpers.test-d.ts b/packages/dts-test/setupHelpers.test-d.ts index a3ab02cab97..d5d332daa1b 100644 --- a/packages/dts-test/setupHelpers.test-d.ts +++ b/packages/dts-test/setupHelpers.test-d.ts @@ -143,6 +143,25 @@ describe('defineEmits w/ type declaration', () => { emit2('baz') }) +describe('defineEmits w/ alt type declaration', () => { + const emit = defineEmits<{ + foo: [id: string] + bar: any[] + baz: [] + }>() + + emit('foo', 'hi') + // @ts-expect-error + emit('foo') + + emit('bar') + emit('bar', 1, 2, 3) + + emit('baz') + // @ts-expect-error + emit('baz', 1) +}) + describe('defineEmits w/ runtime declaration', () => { const emit = defineEmits({ foo: () => {}, diff --git a/packages/runtime-core/src/apiSetupHelpers.ts b/packages/runtime-core/src/apiSetupHelpers.ts index 5ce6fbbd6d1..91f4e39e32e 100644 --- a/packages/runtime-core/src/apiSetupHelpers.ts +++ b/packages/runtime-core/src/apiSetupHelpers.ts @@ -1,4 +1,10 @@ -import { isArray, isPromise, isFunction, Prettify } from '@vue/shared' +import { + isArray, + isPromise, + isFunction, + Prettify, + UnionToIntersection +} from '@vue/shared' import { getCurrentInstance, setCurrentInstance, @@ -120,7 +126,9 @@ export function defineEmits( export function defineEmits( emitOptions: E ): EmitFn -export function defineEmits(): TypeEmit +export function defineEmits< + T extends ((...args: any[]) => any) | Record +>(): T extends (...args: any[]) => any ? T : ShortEmits // implementation export function defineEmits() { if (__DEV__) { @@ -129,6 +137,14 @@ export function defineEmits() { return null as any } +type RecordToUnion> = T[keyof T] + +type ShortEmits> = UnionToIntersection< + RecordToUnion<{ + [K in keyof T]: (evt: K, ...args: T[K]) => void + }> +> + /** * Vue `