FunctionalComponent,
ComponentPublicInstance,
toRefs,
- SetupContext
+ SetupContext,
+ EmitsOptions
} from 'vue'
import { describe, expectAssignable, expectType, IsAny } from './utils'
-declare function extractComponentOptions<Props, RawBindings>(
- obj: Component<Props, RawBindings>
+declare function extractComponentOptions<
+ Props,
+ RawBindings,
+ Emits extends EmitsOptions | Record<string, any[]>,
+ Slots extends Record<string, any>
+>(
+ obj: Component<Props, RawBindings, any, any, any, Emits, Slots>
): {
props: Props
+ emits: Emits
+ slots: Slots
rawBindings: RawBindings
setup: ShallowUnwrapRef<RawBindings>
}
})
describe('typed', () => {
- const MyComponent: FunctionalComponent<{ foo: number }> = (_, _2) => {}
+ type Props = { foo: number }
+ type Emits = { change: [value: string]; inc: [value: number] }
+ type Slots = { default: (scope: { foo: string }) => any }
+
+ const MyComponent: FunctionalComponent<Props, Emits, Slots> = (
+ props,
+ { emit, slots }
+ ) => {
+ expectType<Props>(props)
+ expectType<{
+ (event: 'change', value: string): void
+ (event: 'inc', value: number): void
+ }>(emit)
+ expectType<Slots>(slots)
+ }
- const { props } = extractComponentOptions(MyComponent)
+ const { props, emits, slots } = extractComponentOptions(MyComponent)
- expectType<number>(props.foo)
+ expectType<Props>(props)
+ expectType<Emits>(emits)
+ expectType<Slots>(slots)
})
})
expectAssignable<SetupContext<{ b: () => true }>>(wider)
})
+
+ describe('short emits', () => {
+ const {
+ emit
+ }: SetupContext<{
+ a: [val: string]
+ b: [val: number]
+ }> = {} as any
+
+ expectType<{
+ (event: 'a', val: string): void
+ (event: 'b', val: number): void
+ }>(emit)
+ })
})
EmitFn,
emit,
normalizeEmitsOptions,
- EmitsToProps
+ EmitsToProps,
+ ShortEmitsToObject
} from './componentEmits'
import {
EMPTY_OBJ,
export interface FunctionalComponent<
P = {},
- E extends EmitsOptions = {},
- S extends Record<string, any> = any
+ E extends EmitsOptions | Record<string, any[]> = {},
+ S extends Record<string, any> = any,
+ EE extends EmitsOptions = ShortEmitsToObject<E>
> extends ComponentInternalOptions {
// use of any here is intentional so it can be a valid JSX Element constructor
(
- props: P & EmitsToProps<E>,
- ctx: Omit<SetupContext<E, IfAny<S, {}, SlotsType<S>>>, 'expose'>
+ props: P & EmitsToProps<EE>,
+ ctx: Omit<SetupContext<EE, IfAny<S, {}, SlotsType<S>>>, 'expose'>
): any
props?: ComponentPropsOptions<P>
- emits?: E | (keyof E)[]
+ emits?: EE | (keyof EE)[]
slots?: IfAny<S, Slots, SlotsType<S>>
inheritAttrs?: boolean
displayName?: string
RawBindings = any,
D = any,
C extends ComputedOptions = ComputedOptions,
- M extends MethodOptions = MethodOptions
+ M extends MethodOptions = MethodOptions,
+ E extends EmitsOptions | Record<string, any[]> = {},
+ S extends Record<string, any> = any
> =
| ComponentOptions<Props, RawBindings, D, C, M>
- | FunctionalComponent<Props, any>
+ | FunctionalComponent<Props, E, S>
/**
* A type used in public APIs where a component type is expected.
RawBindings = any,
D = any,
C extends ComputedOptions = ComputedOptions,
- M extends MethodOptions = MethodOptions
+ M extends MethodOptions = MethodOptions,
+ E extends EmitsOptions | Record<string, any[]> = {},
+ S extends Record<string, any> = any
> =
- | ConcreteComponent<Props, RawBindings, D, C, M>
+ | ConcreteComponent<Props, RawBindings, D, C, M, E, S>
| ComponentPublicInstanceConstructor<Props>
export type { ComponentOptions }
}
: {}
+export type ShortEmitsToObject<E> = E extends Record<string, any[]>
+ ? {
+ [K in keyof E]: (...args: E[K]) => any
+ }
+ : E
+
export type EmitFn<
Options = ObjectEmitsOptions,
Event extends keyof Options = keyof Options
{
[key in Event]: Options[key] extends (...args: infer Args) => any
? (event: key, ...args: Args) => void
- : (event: key, ...args: any[]) => void
+ : Options[key] extends any[]
+ ? (event: key, ...args: Options[key]) => void
+ : (event: key, ...args: any[]) => void
}[Event]
>