type Func = (...args: readonly any[]) => any;
type Result<T, E> = Ok<T, E> | Err<T, E>;
type AsyncResult<T, E> = Promise<Result<T, E>>;
interface IResult<T, E> {
  isOk(): this is Ok<T, E>;
  isErr(): this is Err<T, E>;
  andThen<R, F>(func: (result: T) => Result<R, F>): Result<R, E | F>;
  unwrap(): T;
  map<R>(func: (result: T) => R): Result<R, E>;
}
declare function ok<T, E = never>(value: T): Ok<T, E>;
declare function err<T = never, E extends string = string>(err: E): Err<T, E>;
declare function err<T = never, E = unknown>(err: E): Err<T, E>;
declare function err<T = never, E extends void = void>(err: E): Err<T, void>;
declare function err<T = never, E = unknown>(err: E): Err<T, E>;
declare function dontThrow<T extends Func, E>(
  func: T,
  bindThis?: unknown,
): (...args: Parameters<T>) => Result<ReturnType<T>, E>;
declare function dontThrowAsync<Args extends readonly any[], ReturnValue, E>(
  func: (...args: Args) => Promise<ReturnValue>,
  bindThis?: unknown,
): (...args: Args) => AsyncResult<ReturnValue, E>;
declare class Ok<T, E> implements IResult<T, E> {
  private val;
  constructor(value: T);
  isOk(): this is Ok<T, E>;
  isErr(): this is Err<T, E>;
  get value(): T;
  andThen<R, F>(func: (result: T) => Result<R, F>): Result<R, F>;
  unwrap(): T;
  map<R>(func: (result: T) => R): Result<R, E>;
}
declare class Err<T, E> implements IResult<T, E> {
  private err;
  constructor(err: E);
  isOk(): this is Ok<T, E>;
  isErr(): this is Err<T, E>;
  get error(): E;
  andThen<R, F>(func: (result: T) => Result<R, F>): Result<R, E>;
  unwrap(): T;
  map<R>(func: (result: T) => R): Result<R, E>;
}
declare class ResultAsync<T, E> implements PromiseLike<Result<T, E>> {
  private promise;
  constructor(promise: Promise<Result<T, E>>);
  static fromPromise<T, E>(promise: Promise<T>): ResultAsync<T, E>;
  then<A, B>(
    onfulfilled?: (value: Result<T, E>) => A | PromiseLike<A>,
    onrejected?: (reason: unknown) => B | PromiseLike<B>,
  ): PromiseLike<A | B>;
  andThen<R, F>(
    func: (result: T) => Result<R, F> | Promise<Result<R, F>>,
  ): ResultAsync<R, E | F>;
}

export {
  type AsyncResult,
  Err,
  type IResult,
  Ok,
  type Result,
  ResultAsync,
  dontThrow,
  dontThrowAsync,
  err,
  ok,
};
