import { Vue, CreateElement, CombinedVueInstance } from "./vue"; import { VNode, VNodeData, VNodeDirective, NormalizedScopedSlot } from "./vnode"; type Constructor = { new (...args: any[]): any; } // we don't support infer props in async component // N.B. ComponentOptions is contravariant, the default generic should be bottom type export type Component, Methods=DefaultMethods, Computed=DefaultComputed, Props=DefaultProps> = | typeof Vue | FunctionalComponentOptions | ComponentOptions type EsModule = T | { default: T } type ImportedComponent, Methods=DefaultMethods, Computed=DefaultComputed, Props=DefaultProps> = EsModule> export type AsyncComponent, Methods=DefaultMethods, Computed=DefaultComputed, Props=DefaultProps> = AsyncComponentPromise | AsyncComponentFactory export type AsyncComponentPromise, Methods=DefaultMethods, Computed=DefaultComputed, Props=DefaultProps> = ( resolve: (component: Component) => void, reject: (reason?: any) => void ) => Promise> | void; export type AsyncComponentFactory, Methods=DefaultMethods, Computed=DefaultComputed, Props=DefaultProps> = () => { component: Promise>; loading?: ImportedComponent; error?: ImportedComponent; delay?: number; timeout?: number; } /** * When the `Computed` type parameter on `ComponentOptions` is inferred, * it should have a property with the return type of every get-accessor. * Since there isn't a way to query for the return type of a function, we allow TypeScript * to infer from the shape of `Accessors` and work backwards. */ export type Accessors = { [K in keyof T]: (() => T[K]) | ComputedOptions } type DataDef = Data | ((this: Readonly & V) => Data) /** * This type should be used when an array of strings is used for a component's `props` value. */ export type ThisTypedComponentOptionsWithArrayProps = object & ComponentOptions, V>, Methods, Computed, PropNames[], Record> & ThisType>>>; /** * This type should be used when an object mapped to `PropOptions` is used for a component's `props` value. */ export type ThisTypedComponentOptionsWithRecordProps = object & ComponentOptions, Methods, Computed, RecordPropsDefinition, Props> & ThisType>>; type DefaultData = object | ((this: V) => object); type DefaultProps = Record; type DefaultMethods = { [key: string]: (this: V, ...args: any[]) => any }; type DefaultComputed = { [key: string]: any }; export interface ComponentOptions< V extends Vue, Data=DefaultData, Methods=DefaultMethods, Computed=DefaultComputed, PropsDef=PropsDefinition, Props=DefaultProps> { data?: Data; props?: PropsDef; propsData?: object; computed?: Accessors; methods?: Methods; watch?: Record | WatchHandler>; el?: Element | string; template?: string; // hack is for functional component type inference, should not be used in user code render?(createElement: CreateElement, hack: RenderContext): VNode; renderError?(createElement: CreateElement, err: Error): VNode; staticRenderFns?: ((createElement: CreateElement) => VNode)[]; beforeCreate?(this: V): void; created?(): void; beforeDestroy?(): void; destroyed?(): void; beforeMount?(): void; mounted?(): void; beforeUpdate?(): void; updated?(): void; activated?(): void; deactivated?(): void; errorCaptured?(err: Error, vm: Vue, info: string): boolean | void; serverPrefetch?(this: V): Promise; directives?: { [key: string]: DirectiveFunction | DirectiveOptions }; components?: { [key: string]: Component | AsyncComponent }; transitions?: { [key: string]: object }; filters?: { [key: string]: Function }; provide?: object | (() => object); inject?: InjectOptions; model?: { prop?: string; event?: string; }; parent?: Vue; mixins?: (ComponentOptions | typeof Vue)[]; name?: string; // TODO: support properly inferred 'extends' extends?: ComponentOptions | typeof Vue; delimiters?: [string, string]; comments?: boolean; inheritAttrs?: boolean; } export interface FunctionalComponentOptions> { name?: string; props?: PropDefs; model?: { prop?: string; event?: string; }; inject?: InjectOptions; functional: boolean; render?(this: undefined, createElement: CreateElement, context: RenderContext): VNode | VNode[]; } export interface RenderContext { props: Props; children: VNode[]; slots(): any; data: VNodeData; parent: Vue; listeners: { [key: string]: Function | Function[] }; scopedSlots: { [key: string]: NormalizedScopedSlot }; injections: any } export type Prop = { (): T } | { new(...args: never[]): T & object } | { new(...args: string[]): Function } export type PropType = Prop | Prop[]; export type PropValidator = PropOptions | PropType; export interface PropOptions { type?: PropType; required?: boolean; default?: T | null | undefined | (() => T | null | undefined); validator?(value: T): boolean; } export type RecordPropsDefinition = { [K in keyof T]: PropValidator } export type ArrayPropsDefinition = (keyof T)[]; export type PropsDefinition = ArrayPropsDefinition | RecordPropsDefinition; export interface ComputedOptions { get?(): T; set?(value: T): void; cache?: boolean; } export type WatchHandler = string | ((val: T, oldVal: T) => void); export interface WatchOptions { deep?: boolean; immediate?: boolean; } export interface WatchOptionsWithHandler extends WatchOptions { handler: WatchHandler; } export interface DirectiveBinding extends Readonly { readonly modifiers: { [key: string]: boolean }; } export type DirectiveFunction = ( el: HTMLElement, binding: DirectiveBinding, vnode: VNode, oldVnode: VNode ) => void; export interface DirectiveOptions { bind?: DirectiveFunction; inserted?: DirectiveFunction; update?: DirectiveFunction; componentUpdated?: DirectiveFunction; unbind?: DirectiveFunction; } export type InjectKey = string | symbol; export type InjectOptions = { [key: string]: InjectKey | { from?: InjectKey, default?: any } } | string[];