declare global {
	interface SymbolConstructor {
		readonly observable: symbol;
	}
}

type Maybe<T> = T | null | undefined;
type Defined<T> = T extends undefined ? never : T;
type Flags = 's' | 'd' | '';
type ResolveFlags<T, F extends Flags, D = T> = Extract<F, 'd'> extends never ? T : D extends undefined ? T : Defined<T>;

type Params = Record<string, unknown>;
declare class ValidationError extends Error {
    value: any;
    path?: string;
    type?: string;
    errors: string[];
    params?: Params;
    inner: ValidationError[];
    static formatError(message: string | ((params: Params) => string) | unknown, params: Params): any;
    static isError(err: any): err is ValidationError;
    constructor(errorOrErrors: string | ValidationError | readonly ValidationError[], value?: any, field?: string, type?: string, disableStack?: boolean);
    [Symbol.toStringTag]: string;
}

type PanicCallback = (err: Error) => void;
type NextCallback = (err: ValidationError[] | ValidationError | null) => void;
type CreateErrorOptions = {
    path?: string;
    message?: Message<any>;
    params?: ExtraParams;
    type?: string;
    disableStackTrace?: boolean;
};
type TestContext<TContext = {}> = {
    path: string;
    options: ValidateOptions<TContext>;
    originalValue: any;
    parent: any;
    from?: Array<{
        schema: ISchema<any, TContext>;
        value: any;
    }>;
    schema: any;
    resolve: <T>(value: T | Reference<T>) => T;
    createError: (params?: CreateErrorOptions) => ValidationError;
};
type TestFunction<T = unknown, TContext = {}> = (this: TestContext<TContext>, value: T, context: TestContext<TContext>) => void | boolean | ValidationError | Promise<boolean | ValidationError>;
type TestOptions<TSchema extends AnySchema = AnySchema> = {
    value: any;
    path?: string;
    options: InternalOptions;
    originalValue: any;
    schema: TSchema;
};
type TestConfig<TValue = unknown, TContext = {}> = {
    name?: string;
    message?: Message<any>;
    test: TestFunction<TValue, TContext>;
    params?: ExtraParams;
    exclusive?: boolean;
    skipAbsent?: boolean;
};
type Test = ((opts: TestOptions, panic: PanicCallback, next: NextCallback) => void) & {
    OPTIONS?: TestConfig;
};

declare class ReferenceSet extends Set<unknown | Reference> {
    describe(): unknown[];
    resolveAll(resolve: (v: unknown | Reference) => unknown): unknown[];
    clone(): ReferenceSet;
    merge(newItems: ReferenceSet, removeItems: ReferenceSet): ReferenceSet;
}

type SchemaSpec<TDefault> = {
    coerce: boolean;
    nullable: boolean;
    optional: boolean;
    default?: TDefault | (() => TDefault);
    abortEarly?: boolean;
    strip?: boolean;
    strict?: boolean;
    recursive?: boolean;
    disableStackTrace?: boolean;
    label?: string | undefined;
    meta?: SchemaMetadata;
};
interface CustomSchemaMetadata {
}
type SchemaMetadata = keyof CustomSchemaMetadata extends never ? Record<PropertyKey, any> : CustomSchemaMetadata;
type SchemaOptions<TType, TDefault> = {
    type: string;
    spec?: Partial<SchemaSpec<TDefault>>;
    check: (value: any) => value is NonNullable<TType>;
};
type AnySchema<TType = any, C = any, D = any, F extends Flags = Flags> = Schema<TType, C, D, F>;
interface CastOptions$1<C = {}> {
    parent?: any;
    context?: C;
    assert?: boolean;
    stripUnknown?: boolean;
    path?: string;
    resolved?: boolean;
}
interface CastOptionalityOptions<C = {}> extends Omit<CastOptions$1<C>, 'assert'> {
    /**
     * Whether or not to throw TypeErrors if casting fails to produce a valid type.
     * defaults to `true`. The `'ignore-optionality'` options is provided as a migration
     * path from pre-v1 where `schema.nullable().required()` was allowed. When provided
     * cast will only throw for values that are the wrong type *not* including `null` and `undefined`
     */
    assert: 'ignore-optionality';
}
type RunTest = (opts: TestOptions, panic: PanicCallback, next: NextCallback) => void;
type TestRunOptions = {
    tests: RunTest[];
    path?: string | undefined;
    options: InternalOptions;
    originalValue: any;
    value: any;
};
interface SchemaRefDescription {
    type: 'ref';
    key: string;
}
interface SchemaInnerTypeDescription extends SchemaDescription {
    innerType?: SchemaFieldDescription | SchemaFieldDescription[];
}
interface SchemaObjectDescription extends SchemaDescription {
    fields: Record<string, SchemaFieldDescription>;
}
interface SchemaLazyDescription {
    type: string;
    label?: string;
    meta?: SchemaMetadata;
}
type SchemaFieldDescription = SchemaDescription | SchemaRefDescription | SchemaObjectDescription | SchemaInnerTypeDescription | SchemaLazyDescription;
interface SchemaDescription {
    type: string;
    label?: string;
    meta?: SchemaMetadata;
    oneOf: unknown[];
    notOneOf: unknown[];
    default?: unknown;
    nullable: boolean;
    optional: boolean;
    tests: Array<{
        name?: string;
        params: ExtraParams | undefined;
    }>;
}
declare abstract class Schema<TType = any, TContext = any, TDefault = any, TFlags extends Flags = ''> implements ISchema<TType, TContext, TFlags, TDefault> {
    readonly type: string;
    readonly __outputType: ResolveFlags<TType, TFlags, TDefault>;
    readonly __context: TContext;
    readonly __flags: TFlags;
    readonly __isYupSchema__: boolean;
    readonly __default: TDefault;
    readonly deps: readonly string[];
    tests: Test[];
    transforms: TransformFunction<AnySchema>[];
    private conditions;
    private _mutate?;
    private internalTests;
    protected _whitelist: ReferenceSet;
    protected _blacklist: ReferenceSet;
    protected exclusiveTests: Record<string, boolean>;
    protected _typeCheck: (value: any) => value is NonNullable<TType>;
    spec: SchemaSpec<any>;
    constructor(options: SchemaOptions<TType, any>);
    get _type(): string;
    clone(spec?: Partial<SchemaSpec<any>>): this;
    label(label: string): this;
    meta(): SchemaMetadata | undefined;
    meta(obj: SchemaMetadata): this;
    withMutation<T>(fn: (schema: this) => T): T;
    concat(schema: this): this;
    concat(schema: AnySchema): AnySchema;
    isType(v: unknown): v is TType;
    resolve(options: ResolveOptions<TContext>): this;
    protected resolveOptions<T extends InternalOptions<any>>(options: T): T;
    /**
     * Run the configured transform pipeline over an input value.
     */
    cast(value: any, options?: CastOptions$1<TContext>): this['__outputType'];
    cast(value: any, options: CastOptionalityOptions<TContext>): this['__outputType'] | null | undefined;
    protected _cast(rawValue: any, options: CastOptions$1<TContext>): any;
    protected _validate(_value: any, options: InternalOptions<TContext> | undefined, panic: (err: Error, value: unknown) => void, next: (err: ValidationError[], value: unknown) => void): void;
    /**
     * Executes a set of validations, either schema, produced Tests or a nested
     * schema validate result.
     */
    protected runTests(runOptions: TestRunOptions, panic: (err: Error, value: unknown) => void, next: (errors: ValidationError[], value: unknown) => void): void;
    asNestedTest({ key, index, parent, parentPath, originalParent, options, }: NestedTestConfig): RunTest;
    validate(value: any, options?: ValidateOptions<TContext>): Promise<this['__outputType']>;
    validateSync(value: any, options?: ValidateOptions<TContext>): this['__outputType'];
    isValid(value: any, options?: ValidateOptions<TContext>): Promise<boolean>;
    isValidSync(value: any, options?: ValidateOptions<TContext>): value is this['__outputType'];
    protected _getDefault(options?: ResolveOptions<TContext>): any;
    getDefault(options?: ResolveOptions<TContext>): TDefault;
    default(def: DefaultThunk<any>): any;
    strict(isStrict?: boolean): this;
    protected nullability(nullable: boolean, message?: Message<any>): this;
    protected optionality(optional: boolean, message?: Message<any>): this;
    optional(): any;
    defined(message?: Message<any>): any;
    nullable(): any;
    nonNullable(message?: Message<any>): any;
    required(message?: Message<any>): any;
    notRequired(): any;
    transform(fn: TransformFunction<this>): this;
    /**
     * Adds a test function to the schema's queue of tests.
     * tests can be exclusive or non-exclusive.
     *
     * - exclusive tests, will replace any existing tests of the same name.
     * - non-exclusive: can be stacked
     *
     * If a non-exclusive test is added to a schema with an exclusive test of the same name
     * the exclusive test is removed and further tests of the same name will be stacked.
     *
     * If an exclusive test is added to a schema with non-exclusive tests of the same name
     * the previous tests are removed and further tests of the same name will replace each other.
     */
    test(options: TestConfig<this['__outputType'], TContext>): this;
    test(test: TestFunction<this['__outputType'], TContext>): this;
    test(name: string, test: TestFunction<this['__outputType'], TContext>): this;
    test(name: string, message: Message, test: TestFunction<this['__outputType'], TContext>): this;
    when(builder: ConditionBuilder<this>): this;
    when(keys: string | string[], builder: ConditionBuilder<this>): this;
    when(options: ConditionConfig<this>): this;
    when(keys: string | string[], options: ConditionConfig<this>): this;
    typeError(message: Message): this;
    oneOf<U extends TType>(enums: ReadonlyArray<U | Reference>, message?: Message<{
        values: any;
    }>): this;
    oneOf(enums: ReadonlyArray<TType | Reference>, message: Message<{
        values: any;
    }>): any;
    notOneOf<U extends TType>(enums: ReadonlyArray<Maybe<U> | Reference>, message?: Message<{
        values: any;
    }>): this;
    strip(strip?: boolean): any;
    /**
     * Return a serialized description of the schema including validations, flags, types etc.
     *
     * @param options Provide any needed context for resolving runtime schema alterations (lazy, when conditions, etc).
     */
    describe(options?: ResolveOptions<TContext>): SchemaDescription;
}
interface Schema<TType = any, TContext = any, TDefault = any, TFlags extends Flags = ''> {
    validateAt(path: string, value: any, options?: ValidateOptions<TContext>): Promise<any>;
    validateSyncAt(path: string, value: any, options?: ValidateOptions<TContext>): any;
    equals: Schema['oneOf'];
    is: Schema['oneOf'];
    not: Schema['notOneOf'];
    nope: Schema['notOneOf'];
}

type ReferenceOptions<TValue = unknown> = {
    map?: (value: unknown) => TValue;
};
declare class Reference<TValue = unknown> {
    readonly key: string;
    readonly isContext: boolean;
    readonly isValue: boolean;
    readonly isSibling: boolean;
    readonly path: any;
    readonly getter: (data: unknown) => unknown;
    readonly map?: (value: unknown) => TValue;
    readonly __isYupRef: boolean;
    constructor(key: string, options?: ReferenceOptions<TValue>);
    getValue(value: any, parent?: {}, context?: {}): TValue;
    /**
     *
     * @param {*} value
     * @param {Object} options
     * @param {Object=} options.context
     * @param {Object=} options.parent
     */
    cast(value: any, options?: {
        parent?: {};
        context?: {};
    }): TValue;
    resolve(): this;
    describe(): SchemaRefDescription;
    toString(): string;
    static isRef(value: any): value is Reference;
}

type ConditionBuilder<T extends ISchema<any, any>> = (values: any[], schema: T, options: ResolveOptions) => ISchema<any>;
type ConditionConfig<T extends ISchema<any>> = {
    is: any | ((...values: any[]) => boolean);
    then?: (schema: T) => ISchema<any>;
    otherwise?: (schema: T) => ISchema<any>;
};
type ResolveOptions<TContext = any> = {
    value?: any;
    parent?: any;
    context?: TContext;
};

interface ISchema<T, C = any, F extends Flags = any, D = any> {
    __flags: F;
    __context: C;
    __outputType: T;
    __default: D;
    cast(value: any, options?: CastOptions$1<C>): T;
    cast(value: any, options: CastOptionalityOptions<C>): T | null | undefined;
    validate(value: any, options?: ValidateOptions<C>): Promise<T>;
    asNestedTest(config: NestedTestConfig): Test;
    describe(options?: ResolveOptions<C>): SchemaFieldDescription;
    resolve(options: ResolveOptions<C>): ISchema<T, C, F>;
}
type DefaultThunk<T, C = any> = T | ((options?: ResolveOptions<C>) => T);
type TransformFunction<T extends AnySchema> = (this: T, value: any, originalValue: any, schema: T) => any;
interface Ancester<TContext> {
    schema: ISchema<any, TContext>;
    value: any;
}
interface ValidateOptions<TContext = {}> {
    /**
     * Only validate the input, skipping type casting and transformation. Default - false
     */
    strict?: boolean;
    /**
     * Return from validation methods on the first error rather than after all validations run. Default - true
     */
    abortEarly?: boolean;
    /**
     * Remove unspecified keys from objects. Default - false
     */
    stripUnknown?: boolean;
    /**
     * When false validations will not descend into nested schema (relevant for objects or arrays). Default - true
     */
    recursive?: boolean;
    /**
     * When true ValidationError instance won't include stack trace information. Default - false
     */
    disableStackTrace?: boolean;
    /**
     * Any context needed for validating schema conditions (see: when())
     */
    context?: TContext;
}
interface InternalOptions<TContext = any> extends ValidateOptions<TContext> {
    __validating?: boolean;
    originalValue?: any;
    index?: number;
    key?: string;
    parent?: any;
    path?: string;
    sync?: boolean;
    from?: Ancester<TContext>[];
}
interface MessageParams {
    path: string;
    value: any;
    originalValue: any;
    label: string;
    type: string;
    spec: SchemaSpec<any> & Record<string, unknown>;
}
type Message<Extra extends Record<string, unknown> = any> = string | ((params: Extra & MessageParams) => unknown) | Record<PropertyKey, unknown>;
type ExtraParams = Record<string, unknown>;
interface NestedTestConfig {
    options: InternalOptions<any>;
    parent: any;
    originalParent: any;
    parentPath: string | undefined;
    key?: string;
    index?: number;
}

interface ResolverOptions {
    model?: 'validateSync' | 'validate';
}
/** yup field rule resolver */
declare function yupFieldRule<SchemaT extends Schema, TContext = {}>(fieldSchema: SchemaT, schemaOptions?: ValidateOptions<TContext>): (val: unknown) => string | true;

export { type ResolverOptions, yupFieldRule };
