semi: false
singleQuote: true
printWidth: 80
+trailingComma: 'none'
+arrowParens: 'avoid'
"lint-staged": "^10.2.10",
"minimist": "^1.2.0",
"npm-run-all": "^4.1.5",
- "prettier": "~1.14.0",
+ "prettier": "^2.3.1",
"puppeteer": "^10.0.0",
"rollup": "~2.38.5",
"rollup-plugin-node-builtins": "^2.1.2",
ComponentPropsOptions,
ExtractDefaultPropTypes
} from './componentProps'
-import { EmitsOptions } from './componentEmits'
+import { EmitsOptions, EmitsToProps } from './componentEmits'
import { isFunction } from '@vue/shared'
import { VNodeProps } from './vnode'
import {
E extends EmitsOptions = Record<string, any>,
EE extends string = string,
PP = PublicProps,
- Props = Readonly<ExtractPropTypes<PropsOrPropOptions>>,
+ Props = Readonly<ExtractPropTypes<PropsOrPropOptions>> & EmitsToProps<E>,
Defaults = ExtractDefaultPropTypes<PropsOrPropOptions>
> = ComponentPublicInstanceConstructor<
CreateComponentPublicInstance<
EE extends string = string
>(
options: ComponentOptionsWithoutProps<
- Props,
+ Props & EmitsToProps<E>,
RawBindings,
D,
C,
string,
((...args: any[]) => any) | null
>
+
export type EmitsOptions = ObjectEmitsOptions | string[]
+export type EmitsToProps<T extends EmitsOptions> = T extends string[]
+ ? {
+ [K in string & `on${Capitalize<T[number]>}`]?: (...args: any[]) => any
+ }
+ : T extends ObjectEmitsOptions
+ ? {
+ [K in string &
+ `on${Capitalize<string & keyof T>}`]?: K extends `on${infer C}`
+ ? T[Uncapitalize<C>] extends null
+ ? (...args: any[]) => any
+ : T[Uncapitalize<C>]
+ : never
+ }
+ : {}
+
export type EmitFn<
Options = ObjectEmitsOptions,
Event extends keyof Options = keyof Options
> = Options extends Array<infer V>
? (event: V, ...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<
- {
- [key in Event]: Options[key] extends ((...args: infer Args) => any)
- ? (event: key, ...args: Args) => void
- : (event: key, ...args: any[]) => void
- }[Event]
- >
+ ? (event: string, ...args: any[]) => void
+ : UnionToIntersection<
+ {
+ [key in Event]: Options[key] extends (...args: infer Args) => any
+ ? (event: key, ...args: Args) => void
+ : (event: key, ...args: any[]) => void
+ }[Event]
+ >
export function emit(
instance: ComponentInternalInstance,
ExtractPropTypes,
ExtractDefaultPropTypes
} from './componentProps'
-import { EmitsOptions } from './componentEmits'
+import { EmitsOptions, EmitsToProps } from './componentEmits'
import { Directive } from './directives'
import {
CreateComponentPublicInstance,
export type RenderFunction = () => VNodeChild
type ExtractOptionProp<T> = T extends ComponentOptionsBase<
- infer P,
- any,
- any,
- any,
- any,
- any,
- any,
- any
+ infer P, // Props
+ any, // RawBindings
+ any, // D
+ any, // C
+ any, // M
+ any, // Mixin
+ any, // Extends
+ any // EmitsOptions
>
- ? unknown extends P ? {} : P
+ ? unknown extends P
+ ? {}
+ : P
: {}
export interface ComponentOptionsBase<
E extends EmitsOptions,
EE extends string = string,
Defaults = {}
->
- extends LegacyOptions<Props, D, C, M, Mixin, Extends>,
+> extends LegacyOptions<Props, D, C, M, Mixin, Extends>,
ComponentInternalOptions,
ComponentCustomOptions {
setup?: (
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
E extends EmitsOptions = EmitsOptions,
- EE extends string = string
+ EE extends string = string,
+ PE = Props & EmitsToProps<E>
> = ComponentOptionsBase<
- Props,
+ PE,
RawBindings,
D,
C,
> & {
props?: undefined
} & ThisType<
- CreateComponentPublicInstance<{}, RawBindings, D, C, M, Mixin, Extends, E>
+ CreateComponentPublicInstance<PE, RawBindings, D, C, M, Mixin, Extends, E>
>
export type ComponentOptionsWithArrayProps<
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
E extends EmitsOptions = EmitsOptions,
EE extends string = string,
- Props = Readonly<{ [key in PropNames]?: any }>
+ Props = Readonly<{ [key in PropNames]?: any }> & EmitsToProps<E>
> = ComponentOptionsBase<
Props,
RawBindings,
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
E extends EmitsOptions = EmitsOptions,
EE extends string = string,
- Props = Readonly<ExtractPropTypes<PropsOptions>>,
+ Props = Readonly<ExtractPropTypes<PropsOptions>> & EmitsToProps<E>,
Defaults = ExtractDefaultPropTypes<PropsOptions>
> = ComponentOptionsBase<
Props,
export type ExtractComputedReturns<T extends any> = {
[key in keyof T]: T[key] extends { get: (...args: any[]) => infer TReturn }
? TReturn
- : T[key] extends (...args: any[]) => infer TReturn ? TReturn : never
+ : T[key] extends (...args: any[]) => infer TReturn
+ ? TReturn
+ : never
}
export type ObjectWatchOptionItem = {
__differentiator?: keyof D | keyof C | keyof M
}
-type MergedHook<T = (() => void)> = T | T[]
+type MergedHook<T = () => void> = T | T[]
export type MergedComponentOptions = ComponentOptions &
MergedComponentOptionsOverride
const get = isFunction(opt)
? opt.bind(publicThis, publicThis)
: isFunction(opt.get)
- ? opt.get.bind(publicThis, publicThis)
- : NOOP
+ ? opt.get.bind(publicThis, publicThis)
+ : NOOP
if (__DEV__ && get === NOOP) {
warn(`Computed property "${key}" has no getter.`)
}
!isFunction(opt) && isFunction(opt.set)
? opt.set.bind(publicThis)
: __DEV__
- ? () => {
- warn(
- `Write operation failed: computed property "${key}" is readonly.`
- )
- }
- : NOOP
+ ? () => {
+ warn(
+ `Write operation failed: computed property "${key}" is readonly.`
+ )
+ }
+ : NOOP
const c = computed({
get,
set
return from
}
return function mergedDataFn(this: ComponentPublicInstance) {
- return (__COMPAT__ &&
- isCompatEnabled(DeprecationTypes.OPTIONS_DATA_MERGE, null)
- ? deepMergeData
- : extend)(
+ return (
+ __COMPAT__ && isCompatEnabled(DeprecationTypes.OPTIONS_DATA_MERGE, null)
+ ? deepMergeData
+ : extend
+ )(
isFunction(to) ? to.call(this, this) : to,
isFunction(from) ? from.call(this, this) : from
)
describe('with mixins', () => {
const MixinA = defineComponent({
+ emits: ['bar'],
props: {
aP1: {
type: String,
})
const MyComponent = defineComponent({
mixins: [MixinA, MixinB, MixinC, MixinD],
+ emits: ['click'],
props: {
// required should make property non-void
z: {
setup(props) {
expectType<string>(props.z)
// props
+ expectType<((...args: any[]) => any) | undefined>(props.onClick)
+ // from Base
+ expectType<((...args: any[]) => any) | undefined>(props.onBar)
expectType<string>(props.aP1)
expectType<boolean | undefined>(props.aP2)
expectType<any>(props.bP1)
render() {
const props = this.$props
// props
+ expectType<((...args: any[]) => any) | undefined>(props.onClick)
+ // from Base
+ expectType<((...args: any[]) => any) | undefined>(props.onBar)
expectType<string>(props.aP1)
expectType<boolean | undefined>(props.aP2)
expectType<any>(props.bP1)
describe('extends with mixins', () => {
const Mixin = defineComponent({
+ emits: ['bar'],
props: {
mP1: {
type: String,
}
})
const Base = defineComponent({
+ emits: ['foo'],
props: {
p1: Boolean,
p2: {
const MyComponent = defineComponent({
extends: Base,
mixins: [Mixin],
+ emits: ['click'],
props: {
// required should make property non-void
z: {
render() {
const props = this.$props
// props
+ expectType<((...args: any[]) => any) | undefined>(props.onClick)
+ // from Mixin
+ expectType<((...args: any[]) => any) | undefined>(props.onBar)
+ // from Base
+ expectType<((...args: any[]) => any) | undefined>(props.onFoo)
expectType<boolean | undefined>(props.p1)
expectType<number>(props.p2)
expectType<string>(props.z)
input: (b: string) => b.length > 1
},
setup(props, { emit }) {
+ expectType<((n: number) => boolean) | undefined>(props.onClick)
+ expectType<((b: string) => boolean) | undefined>(props.onInput)
emit('click', 1)
emit('input', 'foo')
// @ts-expect-error
defineComponent({
emits: ['foo', 'bar'],
setup(props, { emit }) {
+ expectType<((...args: any[]) => any) | undefined>(props.onFoo)
+ expectType<((...args: any[]) => any) | undefined>(props.onBar)
emit('foo')
emit('foo', 123)
emit('bar')
})
describe('componentOptions setup should be `SetupContext`', () => {
- expect<ComponentOptions['setup']>({} as (
- props: Record<string, any>,
- ctx: SetupContext
- ) => any)
+ expect<ComponentOptions['setup']>(
+ {} as (props: Record<string, any>, ctx: SetupContext) => any
+ )
})
describe('extract instance type', () => {
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
-prettier@~1.14.0:
- version "1.14.3"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.14.3.tgz#90238dd4c0684b7edce5f83b0fb7328e48bd0895"
- integrity sha512-qZDVnCrnpsRJJq5nSsiHCE3BYMED2OtsI+cmzIzF1QIfqm5ALf8tEJcO27zV1gKNKRPdhjO0dNWnrzssDQ1tFg==
+prettier@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.npmjs.org/prettier/-/prettier-2.3.1.tgz#76903c3f8c4449bc9ac597acefa24dc5ad4cbea6"
+ integrity sha512-p+vNbgpLjif/+D+DwAZAbndtRrR0md0MwfmOVN9N+2RgyACMT+7tfaRnT+WDPkqnuVwleyuBIG2XBxKDme3hPA==
pretty-format@^26.0.0, pretty-format@^26.6.2:
version "26.6.2"