import type { Prop } from 'vue';
export type PropConstructor<T = any> = (new (...args: any[]) => T & Record<string, unknown>) | (() => T) | PropMethod<T>;
type PropMethod<T, TConstructor = any> = [T] extends [
    ((...args: any) => any) | undefined
] ? {
    new (): TConstructor;
    (): T;
    readonly prototype: TConstructor;
} : never;
type Data = Record<string, unknown>;
export type PropType<T> = PropConstructor<T> | Array<PropConstructor<T>>;
export interface PropOptions<T = any, D = T> {
    type?: PropType<T> | true | null;
    required?: boolean;
    default?: D | DefaultFactory<D> | null | undefined | Record<string, unknown>;
    validator?: (value: T, props: Data) => boolean;
}
type DefaultFactory<T> = (props: Data) => T | null | undefined;
export type ValidatorFunction<T> = (value: T) => boolean;
export interface VueTypeValidateDef<T = unknown, V = ValidatorFunction<T>> extends VueTypeBaseDef<T> {
    readonly validate: (fn: V) => this & {
        validator: V;
    };
}
export type VueProp<T> = VueTypeBaseDef<T> | PropOptions<T>;
export interface VueTypeBaseDef<T = unknown, D = DefaultType<T>, U = T extends NativeType ? T : () => T> extends PropOptions<T> {
    _vueTypes_name: string;
    type?: PropType<T>;
    readonly def: (def?: D) => this & {
        default: U;
    };
    readonly isRequired: this & {
        required: true;
    };
}
export type DefaultType<T> = T extends NativeType ? T : DefaultFactory<T>;
export type NativeType = string | boolean | number | null | undefined | Function;
export type VueTypeDef<T = unknown> = VueTypeBaseDef<T>;
export interface VueTypeShape<T> extends VueTypeBaseDef<T, DefaultType<Partial<T>>, () => Partial<T>> {
    readonly loose: VueTypeLooseShape<T>;
}
export interface VueTypeLooseShape<T> extends VueTypeBaseDef<T, DefaultFactory<Partial<T & Record<string, any>>>, () => Partial<T> & Record<string, any>> {
    readonly loose: VueTypeLooseShape<T>;
    readonly _vueTypes_isLoose: true;
}
export interface WrappedFn {
    (...args: any[]): any;
    __original: (...args: any[]) => any;
}
export type InferPropType<T, NullAsAny = true> = [T] extends [null] ? NullAsAny extends true ? any : null : [T] extends [{
    type: null | true;
}] ? any : [T] extends [ObjectConstructor | {
    type: ObjectConstructor;
}] ? Record<string, any> : [T] extends [BooleanConstructor | {
    type: BooleanConstructor;
}] ? boolean : [T] extends [DateConstructor | {
    type: DateConstructor;
}] ? Date : [T] extends [Array<infer U> | {
    type: Array<infer U>;
}] ? U extends DateConstructor ? Date | InferPropType<U, false> : InferPropType<U, false> : [T] extends [Prop<infer V, infer D>] ? unknown extends V ? IfAny<V, V, D> : V : T;
export type IfAny<T, Y, N> = 0 extends 1 & T ? Y : N;
export {};
