import type { Diff } from './diff';
import type { Matcher } from './matchers';
import type { Constructor, TypeMappings, TypeName } from './types';
/** An assertion function, for sub-expectations and value introspection */
export type AssertionFunction<T = unknown> = (assert: Expectations<T>) => any;
/** Return the type asserted by an {@link AssertionFunction} or `T` */
export type AssertedType<T, F extends AssertionFunction<any>, R = ReturnType<F>> = R extends Expectations<infer I> ? unknown extends I ? T : I : T;
/** Infer the type of a {@link Matcher}  */
export type InferMatcher<T, M extends Matcher> = M extends Matcher<infer I> ? unknown extends I ? T : T & I : never;
/** Recursively infer the type of a {@link Matcher} in a `Record`  */
export type InferToEqual<T> = T extends Matcher<infer V> ? V : T extends Record<any, any> ? {
    [k in keyof T]: InferToEqual<T[k]>;
} : T;
/** Simple wrapper defining the _parent_ instance of an {@link Expectations}. */
export type ExpectationsParent = {
    /** Parent {@link Expectations} instance */
    expectations: Expectations;
    /** Property associating _this_ to the parent */
    prop: string | number | symbol;
};
/** Main class containing all supported expectations */
export declare class Expectations<T = unknown> {
    /** The value associated with this instance */
    readonly value: T;
    /** Optional additional _remarks_ to associate with errors */
    readonly remarks: string | undefined;
    /**
     * An optional {@link ExpectationsParent} defining _this_ to be a
     * child of another {@link Expectations} instance
     */
    readonly parent?: ExpectationsParent | undefined;
    /** The {@link NegativeExpectations} associated with _this_ */
    readonly not: NegativeExpectations<T>;
    /**
     * Create an {@link Expectations} instance associated with the specified
     * value and error remarks.
     *
     * Optionally a parent {@link Expectations} instance can be specified.
     */
    constructor(
    /** The value associated with this instance */
    value: T, 
    /** Optional additional _remarks_ to associate with errors */
    remarks: string | undefined, // required, but migth be undefined
    /**
     * An optional {@link ExpectationsParent} defining _this_ to be a
     * child of another {@link Expectations} instance
     */
    parent?: ExpectationsParent | undefined);
    /** Throw an {@link ExpectationError} associated with _this_ */
    protected _fail(details: string, diff?: Diff): never;
    /**
     * Expects the value to be of the specified _extended_ {@link TypeName type}.
     *
     * Negation: {@link NegativeExpectations.toBeA `not.toBeA(...)`}
     */
    toBeA<Name extends TypeName>(type: Name): Expectations<TypeMappings[Name]>;
    /**
     * Expects the value to be of the specified _extended_ {@link TypeName type},
     * and further validates it with a {@link Matcher}.
     *
     * Negation: {@link NegativeExpectations.toBeA `not.toBeA(...)`}
     */
    toBeA<Name extends TypeName, Mapped extends TypeMappings[Name], Match extends Matcher>(type: Name, matcher: Match): Expectations<InferMatcher<Mapped, Match>>;
    /**
     * Expects the value to be of the specified _extended_ {@link TypeName type},
     * and further asserts it with an {@link AssertionFunction}.
     *
     * Negation: {@link NegativeExpectations.toBeA `not.toBeA(...)`}
     */
    toBeA<Name extends TypeName, Mapped extends TypeMappings[Name], Assert extends AssertionFunction<Mapped>>(type: Name, assertion: Assert): Expectations<AssertedType<Mapped, Assert>>;
    /**
     * Expects the value to be a `Date`, a `string` parseable into a `Date`, or a
     * `number` indicating the milliseconds from the epoch, _strictly after_
     * the specified date.
     *
     * Negation: {@link Expectations.toBeBeforeOrEqual `toBeBeforeOrEqual(...)`}
     */
    toBeAfter(value: Date | number | string, deltaMs?: number): Expectations<T>;
    /**
     * Expects the value to be a `Date`, a `string` parseable into a `Date`, or a
     * `number` indicating the milliseconds from the epoch, _after or equal_
     * the specified date.
     *
     * Negation: {@link Expectations.toBeBefore `toBeBefore(...)`}
     */
    toBeAfterOrEqual(value: Date | number | string, deltaMs?: number): Expectations<T>;
    /**
     * Expects the value to be a `Date`, a `string` parseable into a `Date`, or a
     * `number` indicating the milliseconds from the epoch, _strictly before_
     * the specified date.
     *
     * Negation: {@link Expectations.toBeAfterOrEqual `toBeAfterOrEqual(...)`}
     */
    toBeBefore(value: Date | number | string, deltaMs?: number): Expectations<T>;
    /**
     * Expects the value to be a `Date`, a `string` parseable into a `Date`, or a
     * `number` indicating the milliseconds from the epoch, _before or equal_
     * the specified date.
     *
     * Negation: {@link Expectations.toBeAfter `toBeAfter(...)`}
     */
    toBeBeforeOrEqual(value: Date | number | string, deltaMs?: number): Expectations<T>;
    /**
     * Expects the value to be a `number` within a given +/- _delta_ range of the
     * specified expected value.
     *
     * Negation: {@link NegativeExpectations.toBeCloseTo `not.toBeCloseTo(...)`}
     */
    toBeCloseTo(value: number, delta: number): Expectations<number>;
    /**
     * Expects the value to be a `bigint` within a given +/- _delta_ range of the
     * specified expected value.
     *
     * Negation: {@link NegativeExpectations.toBeCloseTo `not.toBeCloseTo(...)`}
     */
    toBeCloseTo(value: bigint, delta: bigint): Expectations<bigint>;
    /**
     * Expects the value to be neither `null` nor `undefined`.
     *
     * Negation: {@link NegativeExpectations.toBeDefined `not.toBeDefined()`}
     */
    toBeDefined(): Expectations<T>;
    /**
     * Expect the value to be an instance of {@link Error}.
     *
     * If specified, the {@link Error}'s own message will be further expected to
     * either match the specified {@link RegExp}, or equal the specified `string`.
     */
    toBeError(message?: string | RegExp, substring?: boolean): Expectations<Error>;
    /**
     * Expect the value to be an instance of {@link Error} and further asserts
     * it to be an instance of the specifed {@link Error} {@link Constructor}.
     *
     * If specified, the {@link Error}'s own message will be further expected to
     * either match the specified {@link RegExp}, or equal the specified `string`.
     */
    toBeError<Class extends Constructor<Error>>(constructor: Class, message?: string | RegExp, substring?: boolean): Expectations<InstanceType<Class>>;
    /** Expects the value strictly equal to `false`. */
    toBeFalse(): Expectations<false>;
    /**
     * Expects the value to be _falsy_ (zero, empty string, `false`, ...).
     *
     * Negation: {@link Expectations.toBeTruthy `toBeTruthy()`}
     */
    toBeFalsy(): Expectations<T>;
    /**
     * Expects the value to be a `number` greater than the specified expected
     * value.
     *
     * Negation: {@link Expectations.toBeLessThanOrEqual `toBeLessThanOrEqual(...)`}
     */
    toBeGreaterThan(value: number): Expectations<number>;
    /**
     * Expects the value to be a `bigint` greater than the specified expected
     * value.
     *
     * Negation: {@link Expectations.toBeLessThanOrEqual `toBeLessThanOrEqual(...)`}
     */
    toBeGreaterThan(value: bigint): Expectations<bigint>;
    /**
     * Expects the value to be a `number`  greater than or equal to the specified
     * expected value.
     *
     * Negation: {@link Expectations.toBeLessThan `toBeLessThan(...)`}
     */
    toBeGreaterThanOrEqual(value: number): Expectations<number>;
    /**
     * Expects the value to be a `bigint` greater than or equal to the specified
     * expected value.
     *
     * Negation: {@link Expectations.toBeLessThan `toBeLessThan(...)`}
     */
    toBeGreaterThanOrEqual(value: bigint): Expectations<bigint>;
    /**
     * Expects the value to be an instance of the specified {@link Constructor}.
     *
     * Negation: {@link NegativeExpectations.toBeInstanceOf `not.toInstanceOf(...)`}
     */
    toBeInstanceOf<Class extends Constructor>(constructor: Class): Expectations<InstanceType<Class>>;
    /**
     * Expects the value to be an instance of the specified {@link Constructor},
     * and further validates it with a {@link Matcher}.
     *
     * Negation: {@link NegativeExpectations.toBeInstanceOf `not.toInstanceOf(...)`}
     */
    toBeInstanceOf<Class extends Constructor, Match extends Matcher>(constructor: Class, matcher: Match): Expectations<InferMatcher<InstanceType<Class>, Match>>;
    /**
     * Expects the value to be an instance of the specified {@link Constructor},
     * and further asserts it with an {@link AssertionFunction}.
     *
     * Negation: {@link NegativeExpectations.toBeInstanceOf `not.toInstanceOf(...)`}
     */
    toBeInstanceOf<Class extends Constructor, Assert extends AssertionFunction<InstanceType<Class>>>(constructor: Class, assertion: Assert): Expectations<AssertedType<InstanceType<Class>, Assert>>;
    /**
     * Expects the value to be a `number` less than the specified expected value.
     *
     * Negation: {@link Expectations.toBeGreaterThanOrEqual `toBeGreaterThanOrEqual(...)`}
     */
    toBeLessThan(value: number): Expectations<number>;
    /**
     * Expects the value to be a `bigint` less than the specified expected value.
     *
     * Negation: {@link Expectations.toBeGreaterThanOrEqual `toBeGreaterThanOrEqual(...)`}
     */
    toBeLessThan(value: bigint): Expectations<bigint>;
    /**
     * Expects the value to be a `number` less than or equal to the specified
     * expected value.
     *
     * Negation: {@link Expectations.toBeGreaterThan `toBeGreaterThan(...)`}
     */
    toBeLessThanOrEqual(value: number): Expectations<number>;
    /**
     * Expects the value to be a `bigint` less than or equal to the specified
     * expected value.
     *
     * Negation: {@link Expectations.toBeGreaterThan `toBeGreaterThan(...)`}
     */
    toBeLessThanOrEqual(value: bigint): Expectations<bigint>;
    /**
     * Expects the value to be `NaN`.
     *
     * Negation: {@link NegativeExpectations.toBeNaN `not.toBeNaN()`}
     */
    toBeNaN(): Expectations<number>;
    /** Expects the value to strictly equal `null`. */
    toBeNull(): Expectations<null>;
    /** Expects the value to strictly equal `true`. */
    toBeTrue(): Expectations<true>;
    /**
     * Expects the value to be _falsy_ (non-zero, non-empty string, ...).
     *
     * Negation: {@link Expectations.toBeFalsy `toBeFalsy()`}
     */
    toBeTruthy(): Expectations<T>;
    /** Expects the value to strictly equal `undefined`. */
    toBeUndefined(): Expectations<undefined>;
    /**
     * Expects the value to be a `number` within the specified range where the
     * minimum and maximum values are inclusive.
     *
     * Negation: {@link NegativeExpectations.toBeWithinRange `not.toBeWithinRange(...)`}
     */
    toBeWithinRange(min: number, max: number): Expectations<number>;
    /**
     * Expects the value to be a `bigint` within the specified range where the
     * minimum and maximum values are inclusive.
     *
     * Negation: {@link NegativeExpectations.toBeWithinRange `not.toBeWithinRange(...)`}
     */
    toBeWithinRange(min: bigint, max: bigint): Expectations<bigint>;
    /**
     * Expects the value to be _deep equal to_ the specified expected one.
     *
     * When `strict` is `true` (defaults to `false`) enumerable keys associated
     * with an `undefined` value found in the _actual_ object will have to be
     * also defined in the _expected_ object.
     *
     * For example:
     *
     * ```ts
     * // non-strict mode
     * expect({ foo: undefined }).toEqual({}) // will pass
     * expect({}).toEqual({ foo: undefined }) // will pass
     * expect({ foo: undefined }).toEqual({ foo: undefined }) // will pass
     *
     * // strict mode
     * expect({ foo: undefined }).toEqual({}, true) // will fail
     * expect({}).toEqual({ foo: undefined }, true) // will fail
     * expect({}).toEqual({ foo: undefined }) // will fail ("foo" is missing, whether "strict" is true or false)
     * ```
     *
     * Negation: {@link NegativeExpectations.toEqual `not.toEqual(...)`}
     */
    toEqual<Type>(expected: Type, strict?: boolean): Expectations<InferToEqual<Type>>;
    /**
     * Expects the value to have a `number` _property_ `length` with the specified
     * expected value.
     *
     * Negation: {@link NegativeExpectations.toHaveLength `not.toHaveLength(...)`}
     */
    toHaveLength(length: number): Expectations<T & {
        length: number;
    }>;
    /**
     * Expects the value to have the specified _property_.
     *
     * The value associated with the property should not be `undefined`.
     *
     * For example:
     *
     * ```ts
     * expect({}).toHaveProperty('foo') // fails
     * expect({ foo: undefined }).toHaveProperty('foo') // fails
     * ```
     *
     * Negation: {@link NegativeExpectations.toHaveProperty `not.toHaveProperty(...)`}
     */
    toHaveProperty<Prop extends string | number | symbol>(property: Prop): Expectations<T & {
        [keyt in Prop]: unknown;
    }>;
    /**
     * Expects the value to have the specified _property_ and (if found)
     * further validates its value with a {@link Matcher}.
     *
     * This also works with `undefined` values, for example:
     * ```ts
     * expect({ foo: undefined }).toHaveProperty('foo') // no matcher, fails
     * expect({ foo: undefined }).toHaveProperty('foo', expect.toBeUndefined()) // works!
     * ```
     *
     * Negation: {@link NegativeExpectations.toHaveProperty `not.toHaveProperty(...)`}
     */
    toHaveProperty<Prop extends string | number | symbol, Match extends Matcher>(property: Prop, matcher: Match): Expectations<T & {
        [keyt in Prop]: InferMatcher<unknown, Match>;
    }>;
    /**
     * Expects the value to have the specified _property_ and (if specified)
     * further asserts its value with an {@link AssertionFunction}.
     *
     * Negation: {@link NegativeExpectations.toHaveProperty `not.toHaveProperty(...)`}
     */
    toHaveProperty<Prop extends string | number | symbol, Assert extends AssertionFunction>(property: Prop, assertion: Assert): Expectations<T & {
        [keyt in Prop]: AssertedType<unknown, Assert>;
    }>;
    /**
     * Expects the value to have a `number` _property_ `size` with the specified
     * expected value.
     *
     * Negation: {@link NegativeExpectations.toHaveSize `not.toHaveSize(...)`}
     */
    toHaveSize(size: number): Expectations<T & {
        size: number;
    }>;
    /**
     * Expect the value to include _all_ properties from the specified _object_.
     *
     * If the object being expected is a {@link Map}, the properties specified
     * here will be treated as _mappings_ for said {@link Map}.
     *
     * Negation: {@link NegativeExpectations.toInclude `not.toInclude(...)`}
     */
    toInclude<P extends Record<string, any>>(properties: P): Expectations<T>;
    /**
     * Expect the value to include _all_ mappings from the specified {@link Map}.
     *
     * Negation: {@link NegativeExpectations.toInclude `not.toInclude(...)`}
     */
    toInclude(mappings: Map<any, any>): Expectations<T>;
    /**
     * Expect the value to be an {@link Iterable} object includind _all_ values
     * from the specified {@link Set}, in any order.
     *
     * Negation: {@link NegativeExpectations.toInclude `not.toInclude(...)`}
     */
    toInclude(entries: Set<any>): Expectations<T>;
    /**
     * Expect the value to be an {@link Iterable} object includind _all_ values
     * from the specified _array_, in any order.
     *
     * Negation: {@link NegativeExpectations.toInclude `not.toInclude(...)`}
     */
    toInclude(values: any[]): Expectations<T>;
    /**
     * Expects the value to be a `string` _matching_ the specified sub-`string`
     * or {@link RegExp}.
     *
     * Negation: {@link NegativeExpectations.toMatch `not.toMatch(...)`}
     */
    toMatch<Matcher extends string | RegExp>(matcher: Matcher): Expectations<string>;
    /**
     * Expect the value to be an {@link Iterable} object includind _all_ values
     * (and only those values) from the specified _array_ or {@link Set},
     * in any order.
     */
    toMatchContents(contents: any[] | Set<any>): Expectations<T>;
    /**
     * Expects the value to be _strictly equal to_ the specified expected one.
     *
     * Negation: {@link NegativeExpectations.toStrictlyEqual `not.toStrictlyEqual(...)`}
     */
    toStrictlyEqual<Type>(expected: Type): Expectations<Type>;
    /**
     * Expects the value to be a `function` throwing.
     *
     * Negation: {@link NegativeExpectations.toThrow `not.toThrow()`}
     */
    toThrow(): Expectations<() => any>;
    /**
     * Expects the value to be a `function` throwing, and further validates the
     * thrown value with a {@link Matcher}.
     *
     * Negation: {@link NegativeExpectations.toThrow `not.toThrow()`}
     */
    toThrow(matcher: Matcher): Expectations<() => any>;
    /**
     * Expects the value to be a `function` throwing, and further asserts the
     * thrown value with an {@link AssertionFunction}.
     *
     * Negation: {@link NegativeExpectations.toThrow `not.toThrow()`}
     */
    toThrow(assert: AssertionFunction): Expectations<() => any>;
    /**
     * Expects the value to be a `function` throwing an {@link Error}.
     *
     * If specified, the {@link Error}'s own message will be further expected to
     * either match the specified {@link RegExp}, or equal to the specified
     * `string`.
     *
     * Negation: {@link NegativeExpectations.toThrow `not.toThrow()`}
     */
    toThrowError(message?: string | RegExp, substring?: boolean): Expectations<() => any>;
    /**
     * Expects the value to be a `function` throwing an instance of the
     * {@link Error} identified by the specified {@link Constructor}.
     *
     * If specified, the {@link Error}'s own message will be further expected to
     * either match the specified {@link RegExp}, or equal to the specified
     * `string`.
     *
     * Negation: {@link NegativeExpectations.toThrow `not.toThrow()`}
     */
    toThrowError<Class extends Constructor<Error>>(constructor: Class, message?: string | RegExp, substring?: boolean): Expectations<() => any>;
}
/** Negative expectations, as a subset of (meaningful) expectations. */
export declare class NegativeExpectations<T = unknown> {
    /** The {@link Expectations} instance associated with this one */
    private readonly _expectations;
    /** For convenience, the value associated with the {@link Expectations} */
    private readonly _value;
    /**
     * Create a {@link NegativeExpectations} instance associated with the
     * specified (positive) {@link Expectations}.
     */
    constructor(
    /** The {@link Expectations} instance associated with this one */
    _expectations: Expectations<T>);
    /** Throw an {@link ExpectationError} associated with _this_ */
    private _fail;
    /**
     * Expects the value _**NOT**_ to be of the specified _extended_
     * {@link TypeName type}.
     *
     * Negates: {@link Expectations.toBeA `toBeA(...)`}
     */
    toBeA(type: TypeName): Expectations<T>;
    /**
     * Expects the value to be a `number` _**OUTSIDE**_ of the given +/- _delta_
     * range of the specified expected value.
     *
     * Negates: {@link Expectations.toBeCloseTo `toBeCloseTo(...)`}
     */
    toBeCloseTo(value: number, delta: number): Expectations<number>;
    /**
     * Expects the value to be a `bigint` _**OUTSIDE**_ of the given +/- _delta_
     * range of the specified expected value.
     *
     * Negates: {@link Expectations.toBeCloseTo `toBeCloseTo(...)`}
     */
    toBeCloseTo(value: bigint, delta: bigint): Expectations<bigint>;
    /**
     * Expects the value to be either `null` or `undefined`.
     *
     * Negates: {@link Expectations.toBeDefined `toBeDefined()`}
     */
    toBeDefined(): Expectations<null | undefined>;
    /**
     * Expects the value _**NOT**_ to be an instance of the specified
     * {@link Constructor}.
     *
     * Negates: {@link Expectations.toBeInstanceOf `toBeInstanceOf(...)`}
     */
    toBeInstanceOf(constructor: Constructor): Expectations<T>;
    /**
     * Expects the value _**NOT**_ to be `NaN`.
     *
     * Negates: {@link Expectations.toBeNaN `toBeNaN()`}
     */
    toBeNaN(): Expectations<number>;
    /**
     * Expects the value to be a `number` _**OUTSIDE**_ of the specified range
     * where minimum and maximum values are inclusive.
     *
     * Negates: {@link Expectations.toBeWithinRange `toBeWithinRange(...)`}
     */
    toBeWithinRange(min: number, max: number): Expectations<number>;
    /**
     * Expects the value to be a `bigint` _**OUTSIDE**_ of the specified range
     * where minimum and maximum values are inclusive.
     *
     * Negates: {@link Expectations.toBeWithinRange `toBeWithinRange(...)`}
     */
    toBeWithinRange(min: bigint, max: bigint): Expectations<bigint>;
    /**
     * Expects the value _**NOT**_ to be _deep equal to_ the specified expected
     * one.
     *
     * Negates: {@link Expectations.toEqual `toEqual(...)`}
     */
    toEqual(expected: any, strict?: boolean): Expectations<T>;
    /**
     * Expects the value to have a `number` _property_ `length` _different_ from
     * the specified expected value.
     *
     * Negates: {@link Expectations.toHaveLength `toHaveLength(...)`}
     */
    toHaveLength(length: number): Expectations<T & {
        length: number;
    }>;
    /**
     * Expects the value _**NOT**_ to have the specified _property_.
     *
     * Negates: {@link Expectations.toHaveProperty `toHaveProperty(...)`}
     */
    toHaveProperty(property: string | number | symbol): Expectations<T>;
    /**
     * Expects the value to have a `number` _property_ `size` _different_ from
     * the specified expected value.
     *
     * Negates: {@link Expectations.toHaveSize `toHaveSize(...)`}
     */
    toHaveSize(size: number): Expectations<T & {
        size: number;
    }>;
    /**
     * Expect the value to include _none_ of the properties from the specified
     * _object_.
     *
     * If the object being expected is a {@link Map}, the properties specified
     * here will be treated as _mappings_ for said {@link Map}.
     *
     * Negates: {@link Expectations.toInclude `toInclude(...)`}
     */
    toInclude<P extends Record<string, any>>(properties: P): Expectations<T>;
    /**
     * Expect the value to include _none_ of the mappings from the specified
     * {@link Map}.
     *
     * Negates: {@link Expectations.toInclude `toInclude(...)`}
     */
    toInclude(mappings: Map<any, any>): Expectations<T>;
    /**
     * Expect the value to be an {@link Iterable} object includind _none_ of the
     * values from the specified {@link Set}.
     *
     * Negates: {@link Expectations.toInclude `toInclude(...)`}
     */
    toInclude(entries: Set<any>): Expectations<T>;
    /**
     * Expect the value to be an {@link Iterable} object includind _none_ of the
     * values from the specified _array_.
     *
     * Negates: {@link Expectations.toInclude `toInclude(...)`}
     */
    toInclude(values: any[]): Expectations<T>;
    /**
     * Expects the value to be a `string` _**NOT MATCHING**_ the specified
     * sub-`string` or {@link RegExp}.
     *
     * Negates: {@link Expectations.toMatch `toMatch(...)`}
     */
    toMatch(matcher: string | RegExp): Expectations<string>;
    /**
     * Expects the value to be a `function` not throwing anything.
     *
     * Negates: {@link Expectations.toThrow `toThrow(...)`}
     */
    toThrow(): Expectations<() => any>;
    /**
     * Expects the value _**NOT**_ to be _strictly equal to_ the specified
     * expected one.
     *
     * Negates: {@link Expectations.toStrictlyEqual `toStrictlyEqual(...)`}
     */
    toStrictlyEqual(expected: any): Expectations<T>;
}
