types(runtime-core): provide valid type for default $emit (#1498)

This commit is contained in:
Carlos Rodrigues 2020-07-08 16:51:03 +01:00 committed by GitHub
parent f0394e2a61
commit 1e90605c15
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 28 additions and 11 deletions

View File

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

View File

@ -25,6 +25,8 @@ export type EmitFn<
Event extends keyof Options = keyof Options Event extends keyof Options = keyof Options
> = Options extends any[] > = Options extends any[]
? (event: Options[0], ...args: any[]) => void ? (event: Options[0], ...args: any[]) => void
: {} extends Options // if the emit is empty object (usually the default value for emit) should be converted to function
? (event: string, ...args: any[]) => void
: UnionToIntersection< : UnionToIntersection<
{ {
[key in Event]: Options[key] extends ((...args: infer Args) => any) [key in Event]: Options[key] extends ((...args: infer Args) => any)

View File

@ -12,6 +12,7 @@ import { isObject, isArray } from '@vue/shared'
import { RawSlots } from './componentSlots' import { RawSlots } from './componentSlots'
import { FunctionalComponent, Component } from './component' import { FunctionalComponent, Component } from './component'
import { ComponentOptions } from './componentOptions' import { ComponentOptions } from './componentOptions'
import { EmitsOptions } from './componentEmits'
// `h` is a more user-friendly version of `createVNode` that allows omitting the // `h` is a more user-friendly version of `createVNode` that allows omitting the
// props when possible. It is intended for manually written render functions. // props when possible. It is intended for manually written render functions.
@ -107,8 +108,8 @@ export function h(
): VNode ): VNode
// functional component // functional component
export function h<P>( export function h<P, E extends EmitsOptions = {}>(
type: FunctionalComponent<P>, type: FunctionalComponent<P, E>,
props?: (RawProps & P) | ({} extends P ? null : never), props?: (RawProps & P) | ({} extends P ? null : never),
children?: RawChildren | RawSlots children?: RawChildren | RawSlots
): VNode ): VNode

View File

@ -6,7 +6,8 @@ import {
reactive, reactive,
createApp, createApp,
expectError, expectError,
expectType expectType,
ComponentPublicInstance
} from './index' } from './index'
describe('with object props', () => { describe('with object props', () => {
@ -669,4 +670,17 @@ describe('emits', () => {
expectError(this.$emit('nope')) expectError(this.$emit('nope'))
} }
}) })
// without emits
defineComponent({
setup(props, { emit }) {
emit('test', 1)
emit('test')
}
})
// emit should be valid when ComponentPublicInstance is used.
const instance = {} as ComponentPublicInstance
instance.$emit('test', 1)
instance.$emit('test')
}) })