import '@hapi/joi';
type Map<T> = {
    [P in keyof T]: T[P];
};
declare module '@hapi/joi' {
    interface Box<T, R extends boolean> {
        T: T;
        R: R;
    }
    type BoxType<B, nT> = B extends Box<infer oT, infer oR> ? Box<nT, oR> : B;
    type BoxUnion<B, nT> = B extends Box<infer oT, infer oR> ? Box<oT | nT, oR> : B;
    type BoxReq<B, nR extends boolean> = B extends Box<infer oT, infer oR> ? Box<oT, nR> : B;
    type BoxedPrimitive<T extends Box<any, any> = any> = StringSchema<T> | NumberSchema<T> | BooleanSchema<T> | DateSchema<T> | FunctionSchema<T> | ArraySchema<T> | ObjectSchema<T> | AlternativesSchema<T>;
    type primitiveType = string | number | boolean | Function | Date | undefined | null | void;
    type thruthyPrimitiveType = NonNullable<primitiveType>;
    type mappedSchema = SchemaLike | BoxedPrimitive;
    type mappedSchemaMap<T = any> = {
        [K: string]: mappedSchema;
    };
    type extendsGuard<T, S> = S extends T ? S : T;
    function validate<T, S extends mappedSchemaMap>(value: T, schema: S): ValidationResult<extendsGuard<T, extractType<S>>>;
    function validate<T, S extends mappedSchemaMap>(value: T, schema: S, options: ValidationOptions): ValidationResult<extendsGuard<T, extractType<S>>>;
    function validate<T, R, S extends mappedSchemaMap>(value: T, schema: S, options: ValidationOptions, callback: (err: ValidationError, value: extendsGuard<T, extractType<S>>) => R): R;
    function validate<T, R, S extends mappedSchemaMap>(value: T, schema: S, callback: (err: ValidationError, value: extendsGuard<T, extractType<S>>) => R): R;
    interface StringSchema<N extends Box<string | null, boolean> = any> {
        default<T extends string>(value: T, description?: string): StringSchema<Box<N['T'] | T, true>>;
        default(value: any, description?: string): this;
        default(): this;
        valid<T extends string>(...values: T[]): StringSchema<BoxType<N, typeof values[number]>>;
        valid<T extends string>(values: T[]): StringSchema<BoxType<N, typeof values[number]>>;
        valid(...values: any[]): this;
        valid(values: any[]): this;
        allow<T extends string | null>(values: T[]): StringSchema<BoxType<N, string | typeof values[number]>>;
        allow<T extends string | null>(...values: T[]): StringSchema<BoxType<N, string | typeof values[number]>>;
        allow(...values: any[]): this;
        allow(values: any[]): this;
        required(): StringSchema<BoxReq<N, true>>;
        required(): this;
        exist(): StringSchema<BoxReq<N, true>>;
        exist(): this;
        optional(): StringSchema<BoxReq<N, false>>;
        optional(): this;
    }
    function string<T extends string>(): StringSchema<{
        T: extractType<T>;
        R: false;
    }>;
    interface NumberSchema<N extends Box<number | null, boolean> = any> {
        default<T extends number>(value: T, description?: string): NumberSchema<Box<N['T'] | T, true>>;
        default(value: any, description?: string): this;
        default(): this;
        valid<T extends number>(...values: T[]): NumberSchema<BoxType<N, typeof values[number]>>;
        valid<T extends number>(values: T[]): NumberSchema<BoxType<N, typeof values[number]>>;
        valid(...values: any[]): this;
        valid(values: any[]): this;
        allow<T extends number | null>(values: T[]): NumberSchema<BoxType<N, number | typeof values[number]>>;
        allow<T extends number | null>(...values: T[]): NumberSchema<BoxType<N, number | typeof values[number]>>;
        allow(...values: any[]): this;
        allow(values: any[]): this;
        required(): NumberSchema<BoxReq<N, true>>;
        required(): this;
        exist(): NumberSchema<BoxReq<N, true>>;
        exist(): this;
        optional(): NumberSchema<BoxReq<N, false>>;
        optional(): this;
    }
    function number<T extends number>(): NumberSchema<Box<extractType<T>, false>>;
    interface BooleanSchema<N extends Box<boolean | null, boolean> = any> {
        default<T extends boolean>(value: T, description?: string): BooleanSchema<Box<N['T'] | T, true>>;
        default(value: any, description?: string): this;
        default(): this;
        valid<T extends boolean>(...values: T[]): BooleanSchema<BoxType<N, typeof values[number]>>;
        valid<T extends boolean>(values: T[]): BooleanSchema<BoxType<N, typeof values[number]>>;
        valid(...values: any[]): this;
        valid(values: any[]): this;
        allow<T extends boolean | null>(values: T[]): BooleanSchema<BoxType<N, boolean | typeof values[number]>>;
        allow<T extends boolean | null>(...values: T[]): BooleanSchema<BoxType<N, boolean | typeof values[number]>>;
        allow(...values: any[]): this;
        allow(values: any[]): this;
        required(): BooleanSchema<BoxReq<N, true>>;
        required(): this;
        exist(): BooleanSchema<BoxReq<N, true>>;
        exist(): this;
        optional(): BooleanSchema<BoxReq<N, false>>;
        optional(): this;
    }
    function boolean<T extends boolean>(): BooleanSchema<Box<T, false>>;
    interface DateSchema<N extends Box<Date | null, boolean> = any> {
        default<T extends Date>(value: T, description?: string): DateSchema<Box<N['T'] | T, true>>;
        default(value: any, description?: string): this;
        default(): this;
        valid<T extends Date>(...values: T[]): DateSchema<BoxType<N, typeof values[number]>>;
        valid<T extends Date>(values: T[]): DateSchema<BoxType<N, typeof values[number]>>;
        valid(...values: any[]): this;
        valid(values: any[]): this;
        allow<T extends Date | null>(values: T[]): DateSchema<BoxType<N, Date | typeof values[number]>>;
        allow<T extends Date | null>(...values: T[]): DateSchema<BoxType<N, Date | typeof values[number]>>;
        allow(...values: any[]): this;
        allow(values: any[]): this;
        required(): DateSchema<BoxReq<N, true>>;
        required(): this;
        exist(): DateSchema<BoxReq<N, true>>;
        exist(): this;
        optional(): DateSchema<BoxReq<N, false>>;
        optional(): this;
    }
    function date<T extends Date>(): DateSchema<Box<T, false>>;
    interface FunctionSchema<N extends Box<Function, boolean> = any> {
        required(): FunctionSchema<BoxReq<N, true>>;
        required(): this;
        exist(): FunctionSchema<BoxReq<N, true>>;
        exist(): this;
        optional(): FunctionSchema<BoxReq<N, false>>;
        optional(): this;
    }
    function func<T extends Function>(): FunctionSchema<Box<T, false>>;
    type ArrayType<T> = T extends (infer U)[] ? U : never;
    interface ArraySchema<N = null> {
        default<T extends any[]>(value: T, description?: string): ArraySchema<BoxReq<BoxUnion<N, extractType<ArrayType<T>>>, true>>;
        default(value: any, description?: string): this;
        default(): this;
        items<T extends mappedSchema>(type: T): this extends ArraySchema<infer O> ? O extends Box<infer oT, infer oR> ? ArraySchema<BoxType<O, oT | extractType<T>>> : ArraySchema<Box<extractType<T>, false>> : ArraySchema<Box<extractType<T>, false>>;
        required(): ArraySchema<BoxReq<N, true>>;
        required(): this;
        exist(): ArraySchema<BoxReq<N, true>>;
        exist(): this;
        optional(): ArraySchema<BoxReq<N, false>>;
        optional(): this;
    }
    function array(): ArraySchema<Box<never, false>>;
    interface ObjectSchema<N = null> extends AnySchema {
        default<T extends mappedSchemaMap>(value: T, description?: string): ObjectSchema<BoxReq<BoxUnion<N, extractType<T>>, true>>;
        default(value: any, description?: string): this;
        default(): this;
        keys<T extends mappedSchemaMap>(schema: T): this extends ObjectSchema<infer O> ? O extends Box<infer oT, infer oR> ? ObjectSchema<BoxType<O, oT & extractMap<T>>> : ObjectSchema<Box<extractMap<T>, false>> : ObjectSchema<Box<extractMap<T>, false>>;
        pattern<S extends StringSchema, T extends mappedSchema>(pattern: S, schema: T): this extends ObjectSchema<infer O> ? O extends Box<infer oT, infer oR> ? ObjectSchema<BoxType<O, oT | extractMap<{
            [key in extractType<S>]: T;
        }>>> : ObjectSchema<Box<extractMap<{
            [key in extractType<S>]: T;
        }>, false>> : ObjectSchema<Box<extractMap<{
            [key in extractType<S>]: T;
        }>, false>>;
        pattern<T extends mappedSchema>(pattern: RegExp, schema: T): this extends ObjectSchema<infer O> ? O extends Box<infer oT, infer oR> ? ObjectSchema<BoxType<O, oT | extractMap<{
            [key: string]: T;
        }>>> : ObjectSchema<Box<extractMap<{
            [key: string]: T;
        }>, false>> : ObjectSchema<Box<extractMap<{
            [key: string]: T;
        }>, false>>;
        append<T extends mappedSchemaMap | null | undefined>(schema: T): T extends mappedSchemaMap ? this extends ObjectSchema<infer O> ? O extends Box<infer oT, infer oR> ? ObjectSchema<BoxType<O, oT & extractMap<T>>> : ObjectSchema<Box<extractMap<T>, false>> : ObjectSchema<Box<extractMap<T>, false>> : this;
        pattern(pattern: RegExp | SchemaLike, schema: SchemaLike): this;
        required(): ObjectSchema<BoxReq<N, true>>;
        required(): this;
        exist(): ObjectSchema<BoxReq<N, true>>;
        exist(): this;
        optional(): ObjectSchema<BoxReq<N, false>>;
        optional(): this;
    }
    function object<T extends mappedSchemaMap>(schema: T): ObjectSchema<Box<extractMap<T>, false>>;
    interface AlternativesSchema<N = any> extends AnySchema {
        try<T extends mappedSchema[]>(...values: T): this extends AlternativesSchema<infer O> ? O extends Box<infer oT, infer oR> ? AlternativesSchema<BoxType<O, oT | extractType<T>>> : AlternativesSchema<Box<extractType<T>, false>> : AlternativesSchema<Box<extractType<T>, false>>;
        try<T extends mappedSchema[]>(values: T): this extends AlternativesSchema<infer O> ? O extends Box<infer oT, infer oR> ? AlternativesSchema<BoxType<O, oT | extractType<T>>> : AlternativesSchema<Box<extractType<T>, false>> : AlternativesSchema<Box<extractType<T>, false>>;
        try(...types: SchemaLike[]): this;
        try(types: SchemaLike[]): this;
        required(): AlternativesSchema<BoxReq<N, true>>;
        required(): this;
        exist(): AlternativesSchema<BoxReq<N, true>>;
        exist(): this;
        optional(): AlternativesSchema<BoxReq<N, false>>;
        optional(): this;
        when<R, T1 extends mappedSchema, T2 extends mappedSchema, T extends {
            then: T1;
            otherwise: T2;
        }>(ref: R, defs: T): this extends AlternativesSchema<infer O> ? O extends Box<infer oT, infer oR> ? AlternativesSchema<BoxType<O, oT | extractType<T['then']> | extractType<T['otherwise']>>> : AlternativesSchema<Box<extractType<T['then']> | extractType<T['otherwise']>, false>> : AlternativesSchema<Box<extractType<T['then']> | extractType<T['otherwise']>, false>>;
    }
    function alternatives<T extends mappedSchema[]>(...alts: T): AlternativesSchema<Box<extractType<typeof alts[number]>, false>>;
    function alternatives<T extends mappedSchema[]>(alts: T): AlternativesSchema<Box<extractType<typeof alts[number]>, false>>;
    function alt<T extends mappedSchema[]>(...alts: T): AlternativesSchema<Box<extractType<typeof alts[number]>, false>>;
    function alt<T extends mappedSchema[]>(alts: T): AlternativesSchema<Box<extractType<typeof alts[number]>, false>>;
    type MarkRequired<T, B> = {
        [K in keyof T]: T[K] extends BoxedPrimitive<infer D> ? D['R'] extends B ? T[K] : void : B extends false ? T[K] : void;
    };
    type FilterVoid<T extends string | number | symbol, O extends MarkRequired<any, boolean>> = {
        [K in T extends string | number | symbol ? (O[T] extends null | undefined | void ? never : T) : never]: O[K];
    };
    type Required<T> = FilterVoid<keyof T, MarkRequired<T, true>>;
    type Optional<T> = FilterVoid<keyof T, MarkRequired<T, false>>;
    type extractMap<T extends mappedSchemaMap> = Map<{
        [K in keyof Optional<T>]?: extractType<T[K]>;
    }> & Map<{
        [K in keyof Required<T>]: extractType<T[K]>;
    }>;
    type maybeExtractBox<T> = T extends Box<infer O, infer R> ? O : T;
    type extractOne<T extends mappedSchema> = T extends primitiveType ? T : T extends BooleanSchema<infer O> ? maybeExtractBox<O> : T extends StringSchema<infer O> ? maybeExtractBox<O> : T extends NumberSchema<infer O> ? maybeExtractBox<O> : T extends DateSchema<infer O> ? maybeExtractBox<O> : T extends FunctionSchema<infer O> ? maybeExtractBox<O> : T extends ArraySchema<infer O> ? maybeExtractBox<O>[] : T extends ObjectSchema<infer O> ? maybeExtractBox<O> : T extends AlternativesSchema<infer O> ? maybeExtractBox<O> : T extends mappedSchemaMap<infer O> ? maybeExtractBox<O> : T extends AnySchema ? any : any;
    type extractType<T extends mappedSchema> = T extends Array<infer O> ? (O extends SchemaLike ? extractOne<O> : O extends BoxedPrimitive ? extractOne<O> : O) : T extends mappedSchemaMap ? extractMap<T> : T extends SchemaLike ? extractOne<T> : T extends BoxedPrimitive ? extractOne<T> : extractOne<T>;
}
export { validateJoiSchema } from './utils/validator';
