]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
feat(sfc): support more ergnomic defineEmits type syntax (#7992)
authorEvan You <yyx990803@gmail.com>
Thu, 30 Mar 2023 11:24:32 +0000 (19:24 +0800)
committerGitHub <noreply@github.com>
Thu, 30 Mar 2023 11:24:32 +0000 (19:24 +0800)
packages/dts-test/setupHelpers.test-d.ts
packages/runtime-core/src/apiSetupHelpers.ts

index a3ab02cab9779a3bf2fd7f12e0a5417ed99429ad..d5d332daa1bbefd29755232e84654f94cb69bccc 100644 (file)
@@ -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: () => {},
index 5ce6fbbd6d127c69bdadec0814920aa0e1de9f43..91f4e39e32e1f3c80e897e5c125bb8e180e06c43 100644 (file)
@@ -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<EE extends string = string>(
 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__) {
@@ -129,6 +137,14 @@ export function defineEmits() {
   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