Skip to content

Commit 1e90605

Browse files
authored
types(runtime-core): provide valid type for default $emit (#1498)
1 parent f0394e2 commit 1e90605

File tree

4 files changed

+28
-11
lines changed

4 files changed

+28
-11
lines changed

packages/runtime-core/src/component.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ export interface ComponentInternalOptions {
7979

8080
export interface FunctionalComponent<
8181
P = {},
82-
E extends EmitsOptions = Record<string, any>
82+
E extends EmitsOptions = {}
8383
> extends ComponentInternalOptions {
8484
// use of any here is intentional so it can be a valid JSX Element constructor
8585
(props: P, ctx: SetupContext<E>): any

packages/runtime-core/src/componentEmits.ts

+9-7
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,15 @@ export type EmitFn<
2525
Event extends keyof Options = keyof Options
2626
> = Options extends any[]
2727
? (event: Options[0], ...args: any[]) => void
28-
: UnionToIntersection<
29-
{
30-
[key in Event]: Options[key] extends ((...args: infer Args) => any)
31-
? (event: key, ...args: Args) => void
32-
: (event: key, ...args: any[]) => void
33-
}[Event]
34-
>
28+
: {} extends Options // if the emit is empty object (usually the default value for emit) should be converted to function
29+
? (event: string, ...args: any[]) => void
30+
: UnionToIntersection<
31+
{
32+
[key in Event]: Options[key] extends ((...args: infer Args) => any)
33+
? (event: key, ...args: Args) => void
34+
: (event: key, ...args: any[]) => void
35+
}[Event]
36+
>
3537

3638
export function emit(
3739
instance: ComponentInternalInstance,

packages/runtime-core/src/h.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { isObject, isArray } from '@vue/shared'
1212
import { RawSlots } from './componentSlots'
1313
import { FunctionalComponent, Component } from './component'
1414
import { ComponentOptions } from './componentOptions'
15+
import { EmitsOptions } from './componentEmits'
1516

1617
// `h` is a more user-friendly version of `createVNode` that allows omitting the
1718
// props when possible. It is intended for manually written render functions.
@@ -107,8 +108,8 @@ export function h(
107108
): VNode
108109

109110
// functional component
110-
export function h<P>(
111-
type: FunctionalComponent<P>,
111+
export function h<P, E extends EmitsOptions = {}>(
112+
type: FunctionalComponent<P, E>,
112113
props?: (RawProps & P) | ({} extends P ? null : never),
113114
children?: RawChildren | RawSlots
114115
): VNode

test-dts/defineComponent.test-d.tsx

+15-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import {
66
reactive,
77
createApp,
88
expectError,
9-
expectType
9+
expectType,
10+
ComponentPublicInstance
1011
} from './index'
1112

1213
describe('with object props', () => {
@@ -669,4 +670,17 @@ describe('emits', () => {
669670
expectError(this.$emit('nope'))
670671
}
671672
})
673+
674+
// without emits
675+
defineComponent({
676+
setup(props, { emit }) {
677+
emit('test', 1)
678+
emit('test')
679+
}
680+
})
681+
682+
// emit should be valid when ComponentPublicInstance is used.
683+
const instance = {} as ComponentPublicInstance
684+
instance.$emit('test', 1)
685+
instance.$emit('test')
672686
})

0 commit comments

Comments
 (0)