import { Err } from '@hazae41/result';
import { Awaitable } from '../../libs/promises/promises.js';
import { TimedInit, CachedInit, Timed, Cached } from './times.js';

interface FailInit<T> extends TimedInit, CachedInit {
    readonly error: T;
}
declare namespace FailInit {
    type Infer<T> = FailInit<Inner<T>>;
    type Inner<T> = T extends FailInit<infer Inner> ? Inner : never;
}
declare namespace Fail {
    type Infer<T> = Fail<Inner<T>>;
    type Inner<T> = T extends Fail<infer Inner> ? Inner : never;
}
declare class Fail<T> extends Err<T> implements FailInit<T>, Timed, Cached {
    readonly error: T;
    readonly time: number;
    readonly cooldown?: number;
    readonly expiration?: number;
    constructor(error: T, init?: TimedInit & CachedInit);
    static from<T>(init: FailInit<T>): Fail<T>;
    isData(): false;
    isFail(): this is Fail<T>;
    set(inner: unknown): this;
    setErr<U>(inner: U): Fail<U>;
    setInit(init?: TimedInit & CachedInit): Fail<T>;
    mapErr<U>(mapper: (data: T) => Awaitable<U>): Promise<Fail<U>>;
    mapErrSync<U>(mapper: (data: T) => U): Fail<U>;
    /**
     * Transform Result<Promise<T>, E> into Promise<Result<T, E>>
     * @returns `await this.inner` if `Ok`, `this` if `Err`
     */
    await(): Promise<this>;
    /**
     * Transform Result<T, Promise<E>> into Promise<Result<T, E>>
     * @returns `await this.inner` if `Err`, `this` if `Ok`
     */
    awaitErr<T>(this: Fail<PromiseLike<T>>): Promise<Fail<Awaited<T>>>;
    /**
     * Transform Result<Promise<T>, Promise<E>> into Promise<Result<T, E>>
     * @returns `await this.inner`
     */
    awaitAll<T>(this: Fail<PromiseLike<T>>): Promise<Fail<Awaited<T>>>;
}

export { Fail, FailInit };
