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: () => {},
-import { isArray, isPromise, isFunction, Prettify } from '@vue/shared'
+import {
+ isArray,
+ isPromise,
+ isFunction,
+ Prettify,
+ UnionToIntersection
+} from '@vue/shared'
import {
getCurrentInstance,
setCurrentInstance,
export function defineEmits<E extends EmitsOptions = EmitsOptions>(
emitOptions: E
): EmitFn<E>
-export function defineEmits<TypeEmit>(): TypeEmit
+export function defineEmits<
+ T extends ((...args: any[]) => any) | Record<string, any[]>
+>(): T extends (...args: any[]) => any ? T : ShortEmits<T>
// implementation
export function defineEmits() {
if (__DEV__) {
return null as any
}
+type RecordToUnion<T extends Record<string, any>> = T[keyof T]
+
+type ShortEmits<T extends Record<string, any>> = UnionToIntersection<
+ RecordToUnion<{
+ [K in keyof T]: (evt: K, ...args: T[K]) => void
+ }>
+>
+
/**
* Vue `<script setup>` compiler macro for declaring a component's exposed
* instance properties when it is accessed by a parent component via template