/**
 * Utility function to assert that a case is unreachable
 * @param value the value which to check for exhaustiveness
 *
 * @example
 * ```ts
 * declare const value: "a" | "b" | "c";
 *
 * switch (value) {
 *   case "a":
 * 		// do something
 * 		  break;
 *    case "b":
 * 		// do something
 * 		  break;
 *    default: assertUnreachable(value) // TS should complain here
 * }
 *
 * ```
 */
declare function assertUnreachable(value: never): never;
type IsPromiseOrAsyncFunction<T> = T extends AnyAsyncFunction ? true : T extends Promise<any> ? true : false;
type IsFunction<T> = T extends AnyFunction ? true : false;
type IsPromise<T> = T extends AnyPromise ? true : false;
type UnionContainsPromise<Union> = AnyPromise extends Union ? true : false;
type ListContains<Items extends any[]> = Items[number] extends false ? false : true;
type ListContainsPromiseOrAsyncFunction<T extends any[]> = ListContains<{
    [Index in keyof T]: IsPromiseOrAsyncFunction<T[Index]>;
}>;
type ListContainsFunction<T extends any[]> = ListContains<{
    [Index in keyof T]: IsFunction<T[Index]>;
}>;
type ListContainsPromise<T extends any[]> = ListContains<{
    [Index in keyof T]: IsPromise<T[Index]>;
}>;
type Union<T extends any[]> = T[number];
type Unwrap<T> = T extends (...args: any[]) => Promise<infer U> ? U : T extends (...args: any[]) => infer U ? U : T extends Promise<infer U> ? U : T;
type UnwrapList<Items extends any[]> = {
    [Index in keyof Items]: Unwrap<Items[Index]>;
};
type InferPromise<T> = T extends Promise<infer U> ? U : never;
type AnyPromise = Promise<any>;
type AnyFunction<Returning = any> = (...args: any[]) => Returning;
type AnyAsyncFunction<Returning = any> = (...args: any[]) => Promise<Returning>;
type NativeError = globalThis.Error;
type AnyValue = {};

type InferError<T> = T extends Result<any, infer Error> ? Error : never;
type InferValue<T> = T extends Result<infer Value, any> ? Value : T;
type InferErrors<Items extends any[]> = {
    [Index in keyof Items]: InferError<Items[Index]>;
};
type InferValues<Items extends any[]> = {
    [Index in keyof Items]: InferValue<Items[Index]>;
};
type AnyResult = Result<any, any>;
type AnyAsyncResult = AsyncResult<any, any>;
type ValueOr<Value, Err, Or> = [Err] extends [never] ? [Value] extends [never] ? Or : Value : Value | Or;
type ErrorOr<Value, Err, Or> = [Value] extends [never] ? [Err] extends [never] ? Or : Err : Err | Or;
type AccountForFunctionThrowing<Items extends any[]> = ListContainsFunction<Items> extends true ? NativeError : ListContainsPromise<Items> extends true ? NativeError : never;
/**
 * Represents the asynchronous outcome of an operation that can either succeed or fail.
 */
declare class AsyncResult<Value, Err> extends Promise<Result<Value, Err>> {
    /**
     * Utility getter to infer the value type of the result.
     * Note: this getter does not hold any value, it's only used for type inference.
     */
    $inferValue: Value;
    /**
     * Utility getter to infer the error type of the result.
     * Note: this getter does not hold any value, it's only used for type inference.
     */
    $inferError: Err;
    /**
     * Utility getter to check if the current instance is an `AsyncResult`.
     */
    get isAsyncResult(): true;
    /**
     * @returns the result in a tuple format where the first element is the value and the second element is the error.
     * If the result is successful, the error will be `null`. If the result is a failure, the value will be `null`.
     *
     * This method is especially useful when you want to destructure the result into a tuple and use TypeScript's narrowing capabilities.
     *
     * @example Narrowing down the result type using destructuring
     * ```ts
     * declare const result: AsyncResult<number, ErrorA>;
     *
     * const [value, error] = await result.toTuple();
     *
     * if (error) {
     *   // error is ErrorA
     *   return;
     * }
     *
     * // value must be a number
     * ```
     */
    toTuple(): Promise<[
        Err
    ] extends [never] ? [value: Value, error: never] : [Value] extends [never] ? [value: never, error: Err] : [value: Value, error: null] | [value: null, error: Err]>;
    /**
     * @returns the encapsulated error if the result is a failure, otherwise `null`.
     */
    errorOrNull(): Promise<ErrorOr<Value, Err, null>>;
    /**
     * @returns the encapsulated value if the result is successful, otherwise `null`.
     */
    getOrNull(): Promise<ValueOr<Value, Err, null>>;
    /**
     * Retrieves the encapsulated value of the result, or a default value if the result is a failure.
     *
     * @param defaultValue The value to return if the result is a failure.
     *
     * @returns The encapsulated value if the result is successful, otherwise the default value.
     *
     * @example
     * obtaining the value of a result, or a default value
     * ```ts
     * declare const result: AsyncResult<number, Error>;
     *
     * const value = await result.getOrDefault(0); // number
     * ```
     *
     * @example
     * using a different type for the default value
     * ```ts
     * declare const result: AsyncResult<number, Error>;
     *
     * const value = await result.getOrDefault("default"); // number | string
     * ```
     */
    getOrDefault<Else>(defaultValue: Value | Else): Promise<Value | Else>;
    /**
     * Retrieves the value of the result, or transforms the error using the {@link onFailure} callback into a value.
     *
     * @param onFailure callback function which allows you to transform the error into a value. The callback can be async as well.
     * @returns either the value if the result is successful, or the transformed error.
     *
     * @example
     * transforming the error into a value
     * ```ts
     * declare const result: AsyncResult<number, Error>;
     *
     * const value = await result.getOrElse((error) => 0); // number
     * ```
     *
     * @example
     * using an async callback
     * ```ts
     * const value = await result.getOrElse(async (error) => 0); // number
     * ```
     */
    getOrElse<Else>(onFailure: (error: Err) => Else): Promise<Value | Unwrap<Else>>;
    /**
     * Retrieves the encapsulated value of the result, or throws an error if the result is a failure.
     *
     * @returns The encapsulated value if the result is successful.
     *
     * @throws the encapsulated error if the result is a failure.
     *
     * @example
     * obtaining the value of a result, or throwing an error
     * ```ts
     * declare const result: AsyncResult<number, Error>;
     *
     * const value = await result.getOrThrow(); // number
     * ```
     */
    getOrThrow(): Promise<Value>;
    /**
     * Returns the result of the {@link onSuccess} callback when the result represents success or
     * the result of the {@link onFailure} callback when the result represents a failure.
     *
     * > [!NOTE]
     * > Any exceptions that might be thrown inside the callbacks are not caught, so it is your responsibility
     * > to handle these exceptions
     *
     * @param onSuccess callback function to run when the result is successful. The callback can be async as well.
     * @param onFailure callback function to run when the result is a failure. The callback can be async as well.
     * @returns the result of the callback that was executed.
     *
     * @example
     * folding a result to a response-like object
     *
     * ```ts
     * declare const result: AsyncResult<User, NotFoundError | UserDeactivatedError>;
     *
     * const response = await result.fold(
     *   (user) => ({ status: 200, body: user }),
     *   (error) => {
     *     switch (error.type) {
     *       case "not-found":
     *         return { status: 404, body: "User not found" };
     *       case "user-deactivated":
     *         return { status: 403, body: "User is deactivated" };
     *     }
     *   }
     * );
     * ```
     */
    fold<SuccessResult, FailureResult>(onSuccess: (value: Value) => SuccessResult, onFailure: (error: Err) => FailureResult): Promise<Unwrap<SuccessResult> | Unwrap<FailureResult>>;
    /**
     * Calls the {@link action} callback when the result represents a failure. It is meant to be used for
     * side-effects and the operation does not modify the result itself.
     *
     * @param action callback function to run when the result is a failure. The callback can be async as well.
     * @returns the original instance of the result.
     *
     * > [!NOTE]
     * > Any exceptions that might be thrown inside the {@link action} callback are not caught, so it is your responsibility
     * > to handle these exceptions
     *
     * @example
     * adding logging between operations
     * ```ts
     * declare const result: AsyncResult<number, Error>;
     *
     * result
     *   .onFailure((error) => console.error("I'm failing!", error))
     *   .map((value) => value * 2); // proceed with other operations
     * ```
     */
    onFailure(action: (error: Err) => void | Promise<void>): AsyncResult<Value, Err>;
    /**
     * Calls the {@link action} callback when the result represents a success. It is meant to be used for
     * side-effects and the operation does not modify the result itself.
     *
     * @param action callback function to run when the result is successful. The callback can be async as well.
     * @returns the original instance of the result.
     *
     * > [!NOTE]
     * > Any exceptions that might be thrown inside the {@link action} callback are not caught, so it is your responsibility
     * > to handle these exceptions
     *
     * @example
     * adding logging between operations
     * ```ts
     * declare const result: AsyncResult<number, Error>;
     *
     * result
     *   .onSuccess((value) => console.log("I'm a success!", value))
     *   .map((value) => value * 2); // proceed with other operations
     * ```
     *
     * @example
     * using an async callback
     * ```ts
     * declare const result: AsyncResultResult<number, Error>;
     *
     * const asyncResult = await result.onSuccess(async (value) => someAsyncOperation(value));
     * ```
     */
    onSuccess(action: (value: Value) => void | Promise<void>): AsyncResult<Value, Err>;
    /**
     * Transforms the value of a successful result using the {@link transform} callback.
     * The {@link transform} callback can also return other {@link Result} or {@link AsyncResult} instances,
     * which will be returned as-is (the `Error` types will be merged).
     * The operation will be ignored if the result represents a failure.
     *
     * @param transform callback function to transform the value of the result. The callback can be async as well.
     * @returns a new {@linkcode AsyncResult} instance with the transformed value
     *
     * > [!NOTE]
     * > Any exceptions that might be thrown inside the {@link transform} callback are not caught, so it is your responsibility
     * > to handle these exceptions. Please refer to {@linkcode AsyncResult.mapCatching} for a version that catches exceptions
     * > and encapsulates them in a failed result.
     *
     * @example
     * transforming the value of a result
     * ```ts
     * declare const result: AsyncResult<number, Error>;
     *
     * const transformed = result.map((value) => value * 2); // AsyncResult<number, Error>
     * ```
     *
     * @example
     * returning a result instance
     * ```ts
     * declare const result: AsyncResult<number, Error>;
     * declare function multiplyByTwo(value: number): Result<number, Error>;
     *
     * const transformed = result.map((value) => multiplyByTwo(value)); // AsyncResult<number, Error>
     * ```
     *
     * @example
     * doing an async transformation
     * ```ts
     * declare const result: AsyncResult<number, Error>;
     *
     * const transformed = result.map(async (value) => value * 2); // AsyncResult<number, Error>
     * ```
     *
     * @example
     * returning an async result instance
     *
     * ```ts
     * declare const result: AsyncResult<number, Error>;
     * declare function storeValue(value: number): AsyncResult<boolean, Error>;
     *
     * const transformed = result.map((value) => storeValue(value)); // AsyncResult<boolean, Error>
     * ```
     */
    map<ReturnType>(transform: (value: Value) => ReturnType): ReturnType extends Promise<infer PromiseValue> ? PromiseValue extends Result<infer ResultValue, infer ResultError> ? AsyncResult<ResultValue, Err | ResultError> : AsyncResult<PromiseValue, Err> : ReturnType extends Result<infer ResultValue, infer ResultError> ? AsyncResult<ResultValue, Err | ResultError> : AsyncResult<ReturnType, Err>;
    /**
     * Like {@linkcode AsyncResult.map} it transforms the value of a successful result using the {@link transformValue} callback.
     * In addition, it catches any exceptions that might be thrown inside the {@link transformValue} callback and encapsulates them
     * in a failed result.
     *
     * @param transformValue callback function to transform the value of the result. The callback can be async as well.
     * @param transformError callback function to transform any potential caught error while transforming the value.
     * @returns a new {@linkcode AsyncResult} instance with the transformed value
     */
    mapCatching<ReturnType, ErrorType = NativeError>(transformValue: (value: Value) => ReturnType, transformError?: (error: unknown) => ErrorType): ReturnType extends Promise<infer PromiseValue> ? PromiseValue extends Result<infer ResultValue, infer ResultError> ? AsyncResult<ResultValue, Err | ResultError | ErrorType> : AsyncResult<PromiseValue, Err | ErrorType> : ReturnType extends Result<infer ResultValue, infer ResultError> ? AsyncResult<ResultValue, Err | ResultError | ErrorType> : AsyncResult<ReturnType, Err | ErrorType>;
    /**
     * Transforms the encapsulated error of a failed result using the {@link transform} callback into a new error.
     * This can be useful for instance to capture similar or related errors and treat them as a single higher-level error type
     * @param transform callback function to transform the error of the result.
     * @returns new {@linkcode AsyncResult} instance with the transformed error.
     *
     * @example
     * transforming the error of a result
     * ```ts
     * const result = Result.try(() => fetch("https://example.com"))
     *  .mapCatching((response) => response.json() as Promise<Data>)
     *  .mapError((error) => new FetchDataError("Failed to fetch data", { cause: error }));
     * // AsyncResult<Data, FetchDataError>;
     * ```
     */
    mapError<NewError>(transform: (error: Err) => NewError): AsyncResult<Value, NewError>;
    /**
     * Transforms a failed result using the {@link onFailure} callback into a successful result. Useful for falling back to
     * other scenarios when a previous operation fails.
     * The {@link onFailure} callback can also return other {@link Result} or {@link AsyncResult} instances,
     * which will be returned as-is.
     * After a recovery, logically, the result can only be a success. Therefore, the error type is set to `never`, unless
     * the {@link onFailure} callback returns a result-instance with another error type.
     *
     * @param onFailure callback function to transform the error of the result. The callback can be async as well.
     * @returns a new successful {@linkcode AsyncResult} instance when the result represents a failure, or the original instance
     * if it represents a success.
     *
     * > [!NOTE]
     * > Any exceptions that might be thrown inside the {@link onFailure} callback are not caught, so it is your responsibility
     * > to handle these exceptions. Please refer to {@linkcode AsyncResult.recoverCatching} for a version that catches exceptions
     * > and encapsulates them in a failed result.
     *
     * @example
     * transforming the error into a value
     * Note: Since we recover after trying to persist in the database, we can assume that the `DbError` has been taken care
     * of and therefore it has been removed from the final result.
     * ```ts
     * declare function persistInDB(item: Item): AsyncResult<Item, DbError>;
     * declare function persistLocally(item: Item): AsyncResult<Item, IOError>;
     *
     * persistInDB(item).recover(() => persistLocally(item)); // AsyncResult<Item, IOError>
     * ```
     */
    recover<ReturnType>(onFailure: (error: Err) => ReturnType): ReturnType extends Promise<infer PromiseValue> ? PromiseValue extends Result<infer ResultValue, infer ResultError> ? AsyncResult<Value | ResultValue, ResultError> : AsyncResult<PromiseValue | Value, never> : ReturnType extends Result<infer ResultValue, infer ResultError> ? AsyncResult<Value | ResultValue, ResultError> : AsyncResult<Value | ReturnType, never>;
    /**
     * Like {@linkcode AsyncResult.recover} it transforms a failed result using the {@link onFailure} callback into a successful result.
     * In addition, it catches any exceptions that might be thrown inside the {@link onFailure} callback and encapsulates them
     * in a failed result.
     *
     * @param onFailure callback function to transform the error of the result. The callback can be async as well.
     * @returns a new successful {@linkcode AsyncResult} instance when the result represents a failure, or the original instance
     * if it represents a success.
     */
    recoverCatching<ReturnType>(onFailure: (error: Err) => ReturnType): ReturnType extends Promise<infer PromiseValue> ? PromiseValue extends Result<infer ResultValue, infer ResultError> ? AsyncResult<Value | ResultValue, ResultError | NativeError> : AsyncResult<PromiseValue | Value, NativeError> : ReturnType extends Result<infer ResultValue, infer ResultError> ? AsyncResult<Value | ResultValue, ResultError | NativeError> : AsyncResult<Value | ReturnType, NativeError>;
    /**
     * Print-friendly representation of the `AsyncResult` instance.
     */
    toString(): string;
}
/**
 * Represents the outcome of an operation that can either succeed or fail.
 */
declare class Result<Value, Err> {
    private readonly _value;
    private readonly _error;
    private constructor();
    /**
     * Utility getter to infer the value type of the result.
     * Note: this getter does not hold any value, it's only used for type inference.
     */
    $inferValue: Value;
    /**
     * Utility getter to infer the error type of the result.
     * Note: this getter does not hold any value, it's only used for type inference.
     */
    $inferError: Err;
    /**
     * Utility getter that checks if the current instance is a `Result`.
     */
    get isResult(): true;
    /**
     * Retrieves the encapsulated value of the result.
     *
     * @returns The value if the operation was successful, otherwise `undefined`.
     *
     * __Note:__ You can use {@linkcode Result.isOk} to narrow down the type to a successful result.
     *
     * @example
     * obtaining the value of a result, without checking if it's successful
     * ```ts
     * declare const result: Result<number, Error>;
     *
     * result.value; // number | undefined
     * ```
     *
     * @example
     * obtaining the value of a result, after checking for success
     * ```ts
     * declare const result: Result<number, Error>;
     *
     * if (result.isOk()) {
     *   result.value; // number
     * }
     * ```
     */
    get value(): ValueOr<Value, Err, undefined>;
    /**
     * Retrieves the encapsulated error of the result.
     *
     * @returns The error if the operation failed, otherwise `undefined`.
     *
     * > [!NOTE]
     * > You can use {@linkcode Result.isError} to narrow down the type to a failed result.
     *
     * @example
     * obtaining the value of a result, without checking if it's a failure
     * ```ts
     * declare const result: Result<number, Error>;
     *
     * result.error; // Error | undefined
     * ```
     *
     * @example
     * obtaining the error of a result, after checking for failure
     * ```ts
     * declare const result: Result<number, Error>;
     *
     * if (result.isError()) {
     *   result.error; // Error
     * }
     * ```
     */
    get error(): ErrorOr<Value, Err, undefined>;
    private get success();
    private get failure();
    /**
     * Type guard that checks whether the result is successful.
     *
     * @returns `true` if the result is successful, otherwise `false`.
     *
     * @example
     * checking if a result is successful
     * ```ts
     * declare const result: Result<number, Error>;
     *
     * if (result.isOk()) {
     * 	 result.value; // number
     * }
     * ```
     */
    isOk(): this is Result<[Value] extends [never] ? AnyValue : Value, never>;
    /**
     * Type guard that checks whether the result is successful.
     *
     * @returns `true` if the result represents a failure, otherwise `false`.
     *
     * @example
     * checking if a result represents a failure
     * ```ts
     * declare const result: Result<number, Error>;
     *
     * if (result.isError()) {
     * 	 result.error; // Error
     * }
     * ```
     */
    isError(): this is Result<never, [Err] extends [never] ? AnyValue : Err>;
    /**
     * @returns the result in a tuple format where the first element is the value and the second element is the error.
     * If the result is successful, the error will be `null`. If the result is a failure, the value will be `null`.
     *
     * This method is especially useful when you want to destructure the result into a tuple and use TypeScript's narrowing capabilities.
     *
     * @example Narrowing down the result type using destructuring
     * ```ts
     * declare const result: Result<number, ErrorA>;
     *
     * const [value, error] = result.toTuple();
     *
     * if (error) {
     *   // error is ErrorA
     *   return;
     * }
     *
     * // value must be a number
     * ```
     */
    toTuple(): [Err] extends [never] ? [value: Value, error: never] : [Value] extends [never] ? [value: never, error: Err] : [value: Value, error: null] | [value: null, error: Err];
    /**
     * @returns the encapsulated error if the result is a failure, otherwise `null`.
     */
    errorOrNull(): ErrorOr<Value, Err, null>;
    /**
     * @returns the encapsulated value if the result is successful, otherwise `null`.
     */
    getOrNull(): ValueOr<Value, Err, null>;
    /**
     * Retrieves the value of the result, or a default value if the result is a failure.
     *
     * @param defaultValue The value to return if the result is a failure.
     *
     * @returns The encapsulated value if the result is successful, otherwise the default value.
     *
     * @example
     * obtaining the value of a result, or a default value
     * ```ts
     * declare const result: Result<number, Error>;
     *
     * const value = result.getOrDefault(0); // number
     * ```
     *
     * @example
     * using a different type for the default value
     * ```ts
     * declare const result: Result<number, Error>;
     *
     * const value = result.getOrDefault("default"); // number | string
     * ```
     */
    getOrDefault<Else>(defaultValue: Else): Value | Else;
    /**
     * Retrieves the value of the result, or transforms the error using the {@link onFailure} callback into a value.
     *
     * @param onFailure callback function which allows you to transform the error into a value. The callback can be async as well.
     * @returns either the value if the result is successful, or the transformed error.
     *
     * @example
     * transforming the error into a value
     * ```ts
     * declare const result: Result<number, Error>;
     *
     * const value = result.getOrElse((error) => 0); // number
     * ```
     *
     * @example
     * using an async callback
     * ```ts
     * const value = await result.getOrElse(async (error) => 0); // Promise<number>
     * ```
     */
    getOrElse<Else>(onFailure: (error: Err) => Else): Else extends Promise<infer U> ? Promise<Value | U> : Value | Else;
    /**
     * Retrieves the value of the result, or throws an error if the result is a failure.
     *
     * @returns The value if the result is successful.
     *
     * @throws the encapsulated error if the result is a failure.
     *
     * @example
     * obtaining the value of a result, or throwing an error
     * ```ts
     * declare const result: Result<number, Error>;
     *
     * const value = result.getOrThrow(); // number
     * ```
     */
    getOrThrow(): Value;
    /**
     * Returns the result of the {@link onSuccess} callback when the result represents success or
     * the result of the {@link onFailure} callback when the result represents a failure.
     *
     * > [!NOTE]
     * > Any exceptions that might be thrown inside the callbacks are not caught, so it is your responsibility
     * > to handle these exceptions
     *
     * @param onSuccess callback function to run when the result is successful. The callback can be async as well.
     * @param onFailure callback function to run when the result is a failure. The callback can be async as well.
     * @returns the result of the callback that was executed.
     *
     * @example
     * folding a result to a response-like object
     *
     * ```ts
     * declare const result: Result<User, NotFoundError | UserDeactivatedError>;
     *
     * const response = result.fold(
     *   (user) => ({ status: 200, body: user }),
     *   (error) => {
     *     switch (error.type) {
     *       case "not-found":
     *         return { status: 404, body: "User not found" };
     *       case "user-deactivated":
     *         return { status: 403, body: "User is deactivated" };
     *     }
     *   }
     * );
     * ```
     */
    fold<SuccessResult, FailureResult>(onSuccess: (value: Value) => SuccessResult, onFailure: (error: Err) => FailureResult): UnionContainsPromise<SuccessResult | FailureResult> extends true ? Promise<Unwrap<SuccessResult> | Unwrap<FailureResult>> : SuccessResult | FailureResult;
    /**
     * Calls the {@link action} callback when the result represents a failure. It is meant to be used for
     * side-effects and the operation does not modify the result itself.
     *
     * @param action callback function to run when the result is a failure. The callback can be async as well.
     * @returns the original instance of the result.
     *
     * > [!NOTE]
     * > Any exceptions that might be thrown inside the {@link action} callback are not caught, so it is your responsibility
     * > to handle these exceptions
     *
     * @example
     * adding logging between operations
     * ```ts
     * declare const result: Result<number, Error>;
     *
     * result
     *   .onFailure((error) => console.error("I'm failing!", error))
     *   .map((value) => value * 2); // proceed with other operations
     * ```
     */
    onFailure<ReturnValue>(action: (error: Err) => ReturnValue): ReturnValue extends AnyPromise ? AsyncResult<Value, Err> : this;
    /**
     * Calls the {@link action} callback when the result represents a success. It is meant to be used for
     * side-effects and the operation does not modify the result itself.
     *
     * @param action callback function to run when the result is successful. The callback can be async as well.
     * @returns the original instance of the result. If the callback is async, it returns a new {@link AsyncResult} instance.
     *
     * > [!NOTE]
     * > Any exceptions that might be thrown inside the {@link action} callback are not caught, so it is your responsibility
     * > to handle these exceptions
     *
     * @example
     * adding logging between operations
     * ```ts
     * declare const result: Result<number, Error>;
     *
     * result
     *   .onSuccess((value) => console.log("I'm a success!", value))
     *   .map((value) => value * 2); // proceed with other operations
     * ```
     *
     * @example
     * using an async callback
     * ```ts
     * declare const result: Result<number, Error>;
     *
     * const asyncResult = await result.onSuccess(async (value) => someAsyncOperation(value));
     * ```
     */
    onSuccess(action: (value: Value) => Promise<void>): AsyncResult<Value, Err>;
    onSuccess(action: (value: Value) => void): this;
    /**
     * Transforms the value of a successful result using the {@link transform} callback.
     * The {@link transform} callback can also return other {@link Result} or {@link AsyncResult} instances,
     * which will be returned as-is (the `Error` types will be merged).
     * The operation will be ignored if the result represents a failure.
     *
     * @param transform callback function to transform the value of the result. The callback can be async as well.
     * @returns a new {@linkcode Result} instance with the transformed value, or a new {@linkcode AsyncResult} instance
     * if the transform function is async.
     *
     * > [!NOTE]
     * > Any exceptions that might be thrown inside the {@link transform} callback are not caught, so it is your responsibility
     * > to handle these exceptions. Please refer to {@linkcode Result.mapCatching} for a version that catches exceptions
     * > and encapsulates them in a failed result.
     *
     * @example
     * transforming the value of a result
     * ```ts
     * declare const result: Result<number, Error>;
     *
     * const transformed = result.map((value) => value * 2); // Result<number, Error>
     * ```
     *
     * @example
     * returning a result instance
     * ```ts
     * declare const result: Result<number, Error>;
     * declare function multiplyByTwo(value: number): Result<number, Error>;
     *
     * const transformed = result.map((value) => multiplyByTwo(value)); // Result<number, Error>
     * ```
     *
     * @example
     * doing an async transformation
     * ```ts
     * declare const result: Result<number, Error>;
     *
     * const transformed = result.map(async (value) => value * 2); // AsyncResult<number, Error>
     * ```
     *
     * @example
     * returning an async result instance
     *
     * ```ts
     * declare const result: Result<number, Error>;
     * declare function storeValue(value: number): AsyncResult<boolean, Error>;
     *
     * const transformed = result.map((value) => storeValue(value)); // AsyncResult<boolean, Error>
     * ```
     */
    map<ReturnType>(transform: (value: Value) => ReturnType): ReturnType extends Promise<infer PromiseValue> ? PromiseValue extends Result<infer ResultValue, infer ResultError> ? AsyncResult<ResultValue, Err | ResultError> : AsyncResult<PromiseValue, Err> : ReturnType extends Result<infer ResultValue, infer ResultError> ? Result<ResultValue, Err | ResultError> : Result<ReturnType, Err>;
    /**
     * Like {@linkcode Result.map} it transforms the value of a successful result using the {@link transformValue} callback.
     * In addition, it catches any exceptions that might be thrown inside the {@link transformValue} callback and encapsulates them
     * in a failed result.
     *
     * @param transformValue callback function to transform the value of the result. The callback can be async as well.
     * @param transformError callback function to transform any potential caught error while transforming the value.
     * @returns a new {@linkcode Result} instance with the transformed value, or a new {@linkcode AsyncResult} instance
     * if the transform function is async.
     */
    mapCatching<ReturnType, ErrorType = NativeError>(transformValue: (value: Value) => ReturnType, transformError?: (err: unknown) => ErrorType): ReturnType extends Promise<infer PromiseValue> ? PromiseValue extends Result<infer ResultValue, infer ResultError> ? AsyncResult<ResultValue, Err | ResultError | ErrorType> : AsyncResult<PromiseValue, Err | ErrorType> : ReturnType extends Result<infer ResultValue, infer ResultError> ? Result<ResultValue, Err | ResultError | ErrorType> : Result<ReturnType, Err | ErrorType>;
    /**
     * Transforms the encapsulated error of a failed result using the {@link transform} callback into a new error.
     * This can be useful for instance to capture similar or related errors and treat them as a single higher-level error type
     * @param transform callback function to transform the error of the result.
     * @returns new {@linkcode Result} instance with the transformed error.
     *
     * @example
     * transforming the error of a result
     * ```ts
     * declare const result: Result<number, ErrorA>;
     *
     * result.mapError((error) => new ErrorB(error.message)); // Result<number, ErrorB>
     * ```
     */
    mapError<NewError>(transform: (error: Err) => NewError): Result<Value, NewError>;
    /**
     * Transforms a failed result using the {@link onFailure} callback into a successful result. Useful for falling back to
     * other scenarios when a previous operation fails.
     * The {@link onFailure} callback can also return other {@link Result} or {@link AsyncResult} instances,
     * which will be returned as-is.
     * After a recovery, logically, the result can only be a success. Therefore, the error type is set to `never`, unless
     * the {@link onFailure} callback returns a result-instance with another error type.
     *
     * @param onFailure callback function to transform the error of the result. The callback can be async as well.
     * @returns a new successful {@linkcode Result} instance or a new successful {@linkcode AsyncResult} instance
     * when the result represents a failure, or the original instance if it represents a success.
     *
     * > [!NOTE]
     * > Any exceptions that might be thrown inside the {@link onFailure} callback are not caught, so it is your responsibility
     * > to handle these exceptions. Please refer to {@linkcode Result.recoverCatching} for a version that catches exceptions
     * > and encapsulates them in a failed result.
     *
     * @example
     * transforming the error into a value
     * Note: Since we recover after trying to persist in the database, we can assume that the `DbError` has been taken care
     * of and therefore it has been removed from the final result.
     * ```ts
     * declare function persistInDB(item: Item): Result<Item, DbError>;
     * declare function persistLocally(item: Item): Result<Item, IOError>;
     *
     * persistInDB(item).recover(() => persistLocally(item)); // Result<Item, IOError>
     * ```
     */
    recover<ReturnType>(onFailure: (error: Err) => ReturnType): ReturnType extends Promise<infer PromiseValue> ? PromiseValue extends Result<infer ResultValue, infer ResultError> ? AsyncResult<Value | ResultValue, ResultError> : AsyncResult<PromiseValue | Value, never> : ReturnType extends Result<infer ResultValue, infer ResultError> ? Result<Value | ResultValue, ResultError> : Result<Value | ReturnType, never>;
    /**
     * Like {@linkcode Result.recover} it transforms a failed result using the {@link onFailure} callback into a successful result.
     * In addition, it catches any exceptions that might be thrown inside the {@link onFailure} callback and encapsulates them
     * in a failed result.
     *
     * @param onFailure callback function to transform the error of the result. The callback can be async as well.
     * @returns a new successful {@linkcode Result} instance or a new successful {@linkcode AsyncResult} instance
     * when the result represents a failure, or the original instance if it represents a success.
     */
    recoverCatching<ReturnType>(onFailure: (error: Err) => ReturnType): ReturnType extends Promise<infer PromiseValue> ? PromiseValue extends Result<infer ResultValue, infer ResultError> ? AsyncResult<Value | ResultValue, ResultError | NativeError> : AsyncResult<PromiseValue | Value, NativeError> : ReturnType extends Result<infer ResultValue, infer ResultError> ? Result<Value | ResultValue, ResultError | NativeError> : Result<Value | ReturnType, NativeError>;
    /**
     * Returns a string representation of the result.
     */
    toString(): string;
    /**
     * Creates a new result instance that represents a successful outcome.
     *
     * @param value The value to encapsulate in the result.
     * @returns a new {@linkcode Result} instance.
     *
     * @example
     * ```ts
     * const result = Result.ok(42); // Result<number, never>
     * ```
     */
    static ok(): Result<void, never>;
    static ok<Value>(value: Value): Result<Value, never>;
    /**
     * Creates a new result instance that represents a failed outcome.
     *
     * @param error The error to encapsulate in the result.
     * @returns a new {@linkcode Result} instance.
     *
     * @example
     * ```ts
     * const result = Result.error(new NotFoundError()); // Result<never, NotFoundError>
     * ```
     */
    static error<Error>(error: Error): Result<never, Error>;
    /**
     * Type guard that checks whether the provided value is a {@linkcode Result} instance.
     *
     * @param possibleResult any value that might be a {@linkcode Result} instance.
     * @returns true if the provided value is a {@linkcode Result} instance, otherwise false.
     */
    static isResult(possibleResult: unknown): possibleResult is AnyResult;
    /**
     * Type guard that checks whether the provided value is a {@linkcode AsyncResult} instance.
     *
     * @param possibleAsyncResult any value that might be a {@linkcode AsyncResult} instance.
     * @returns true if the provided value is a {@linkcode AsyncResult} instance, otherwise false.
     */
    static isAsyncResult(possibleAsyncResult: unknown): possibleAsyncResult is AnyAsyncResult;
    private static run;
    private static allInternal;
    /**
     * Similar to {@linkcode Promise.all}, but for results.
     * Useful when you want to run multiple independent operations and bundle the outcome into a single result.
     * All possible values of the individual operations are collected into an array. `Result.all` will fail eagerly,
     * meaning that as soon as any of the operations fail, the entire result will be a failure.
     * Each argument can be a mixture of literal values, functions, {@linkcode Result} or {@linkcode AsyncResult} instances, or {@linkcode Promise}.
     *
     * @param items one or multiple literal value, function, {@linkcode Result} or {@linkcode AsyncResult} instance, or {@linkcode Promise}.
     * @returns combined result of all the operations.
     *
     * > [!NOTE]
     * > Any exceptions that might be thrown are not caught, so it is your responsibility
     * > to handle these exceptions. Please refer to {@linkcode Result.allCatching} for a version that catches exceptions
     * > and encapsulates them in a failed result.
     *
     * @example
     * basic usage
     * ```ts
     * declare function createTask(name: string): Result<Task, IOError>;
     *
     * const tasks = ["task-a", "task-b", "task-c"];
     * const result = Result.all(...tasks.map(createTask)); // Result<Task[], IOError>
     * ```
     *
     * @example
     * running multiple operations and combining the results
     * ```ts
     * const result = Result.all(
     *   "a",
     *   Promise.resolve("b"),
     *   Result.ok("c"),
     *   Result.try(async () => "d"),
     *   () => "e",
     *   () => Result.try(async () => "f"),
     *   () => Result.ok("g"),
     *   async () => "h",
     * ); // AsyncResult<[string, string, string, string, string, string, string, string], Error>
     * ```
     */
    static all<Items extends any[], Unwrapped extends any[] = UnwrapList<Items>>(...items: Items): ListContainsPromiseOrAsyncFunction<Items> extends true ? AsyncResult<InferValues<Unwrapped>, Union<InferErrors<Unwrapped>>> : Result<InferValues<Unwrapped>, Union<InferErrors<Unwrapped>>>;
    /**
     * Similar to {@linkcode Result.all}, but catches any exceptions that might be thrown during the operations.
     * @param items one or multiple literal value, function, {@linkcode Result} or {@linkcode AsyncResult} instance, or {@linkcode Promise}.
     * @returns combined result of all the operations.
     */
    static allCatching<Items extends any[], Unwrapped extends any[] = UnwrapList<Items>>(...items: Items): ListContainsPromiseOrAsyncFunction<Items> extends true ? AsyncResult<InferValues<Unwrapped>, Union<InferErrors<Unwrapped>> | AccountForFunctionThrowing<Items>> : Result<InferValues<Unwrapped>, Union<InferErrors<Unwrapped>> | AccountForFunctionThrowing<Items>>;
    /**
     * Wraps a function and returns a new function that returns a result. Especially useful when you want to work with
     * external functions that might throw exceptions.
     * The returned function will catch any exceptions that might be thrown and encapsulate them in a failed result.
     *
     * @param fn function to wrap. Can be synchronous or asynchronous.
     * @returns a new function that returns a result.
     *
     * @example
     * basic usage
     * ```ts
     * declare function divide(a: number, b: number): number;
     *
     * const safeDivide = Result.wrap(divide);
     * const result = safeDivide(10, 0); // Result<number, Error>
     * ```
     */
    static wrap<Fn extends AnyAsyncFunction>(fn: Fn): (...args: Parameters<Fn>) => AsyncResult<InferPromise<ReturnType<Fn>>, NativeError>;
    static wrap<Fn extends AnyFunction>(fn: Fn): (...args: Parameters<Fn>) => Result<ReturnType<Fn>, NativeError>;
    /**
     * Executes the given {@linkcode fn} function and encapsulates the returned value as a successful result, or the
     * thrown exception as a failed result. In a way, you can view this method as a try-catch block that returns a result.
     *
     * @param fn function with code to execute. Can be synchronous or asynchronous.
     * @param transform optional callback to transform the caught error into a more meaningful error.
     * @returns a new {@linkcode Result} instance.
     *
     * @example
     * basic usage
     * ```ts
     * declare function saveFileToDisk(filename: string): void; // might throw an error
     *
     * const result = Result.try(() => saveFileToDisk("file.txt")); // Result<void, Error>
     * ```
     *
     * @example
     * basic usage with error transformation
     * ```ts
     * declare function saveFileToDisk(filename: string): void; // might throw an error
     *
     * const result = Result.try(
     *   () => saveFileToDisk("file.txt"),
     *   (error) => new IOError("Failed to save file", { cause: error })
     * ); // Result<void, IOError>
     * ```
     */
    static try<Fn extends AnyAsyncFunction<AnyResult>, R = InferPromise<ReturnType<Fn>>>(fn: Fn): AsyncResult<InferValue<R>, InferError<R> | NativeError>;
    static try<Fn extends AnyFunction<AnyResult>, R = ReturnType<Fn>>(fn: Fn): Result<InferValue<R>, InferError<R> | NativeError>;
    static try<ReturnType extends AnyPromise>(fn: () => ReturnType): AsyncResult<InferPromise<ReturnType>, NativeError>;
    static try<ReturnType>(fn: () => ReturnType): Result<ReturnType, NativeError>;
    static try<ReturnType extends AnyPromise, ErrorType extends AnyValue>(fn: () => ReturnType, transform: (error: unknown) => ErrorType): AsyncResult<InferPromise<ReturnType>, ErrorType>;
    static try<ReturnType, ErrorType extends AnyValue>(fn: () => ReturnType, transform: (error: unknown) => ErrorType): Result<ReturnType, ErrorType>;
    /**
     * Utility method to transform a Promise, that holds a literal value or
     * a {@linkcode Result} or {@linkcode AsyncResult} instance, into an {@linkcode AsyncResult} instance. Useful when you want to immediately chain operations
     * after calling an async function.
     *
     * @param value a Promise that holds a literal value or a {@linkcode Result} or {@linkcode AsyncResult} instance.
     *
     * @returns a new {@linkcode AsyncResult} instance.
     *
     * > [!NOTE]
     * > Any exceptions that might be thrown are not caught, so it is your responsibility
     * > to handle these exceptions. Please refer to {@linkcode Result.fromAsyncCatching} for a version that catches exceptions
     * > and encapsulates them in a failed result.
     *
     * @example
     * basic usage
     *
     * ```ts
     * declare function someAsyncOperation(): Promise<Result<number, Error>>;
     *
     * // without 'Result.fromAsync'
     * const result = (await someAsyncOperation()).map((value) => value * 2); // Result<number, Error>
     *
     * // with 'Result.fromAsync'
     * const asyncResult = Result.fromAsync(someAsyncOperation()).map((value) => value * 2); // AsyncResult<number, Error>
     * ```
     */
    static fromAsync<T extends Promise<AnyAsyncResult>>(value: T): T extends Promise<AsyncResult<infer V, infer E>> ? AsyncResult<V, E> : never;
    static fromAsync<T extends Promise<AnyResult>>(value: T): T extends Promise<Result<infer V, infer E>> ? AsyncResult<V, E> : never;
    static fromAsync<T extends AnyPromise>(value: T): T extends Promise<infer V> ? AsyncResult<V, never> : never;
    /**
     * Similar to {@linkcode Result.fromAsync} this method transforms a Promise into an {@linkcode AsyncResult} instance.
     * In addition, it catches any exceptions that might be thrown during the operation and encapsulates them in a failed result.
     */
    static fromAsyncCatching<T extends Promise<AnyAsyncResult>>(value: T): T extends Promise<AsyncResult<infer V, infer E>> ? AsyncResult<V, E | NativeError> : never;
    static fromAsyncCatching<T extends Promise<AnyResult>>(value: T): T extends Promise<Result<infer V, infer E>> ? AsyncResult<V, E | NativeError> : never;
    static fromAsyncCatching<T extends AnyPromise>(value: T): T extends Promise<infer V> ? AsyncResult<V, NativeError> : never;
    /**
     * Asserts that the provided result is successful. If the result is a failure, an error is thrown.
     * Useful in unit tests.
     *
     * @param result the result instance to assert against.
     */
    static assertOk<Value>(result: Result<Value, any>): asserts result is Result<Value, never>;
    /**
     * Asserts that the provided result is a failure. If the result is successful, an error is thrown.
     * Useful in unit tests.
     *
     * @param result the result instance to assert against.
     */
    static assertError<Err>(result: Result<any, Err>): asserts result is Result<never, Err>;
}

export { AsyncResult, Result, assertUnreachable };
