/// /** * This file contains the Promise algebraic data type. Promise is the javascript * built in data structure for asynchronous computation. * * @module Promise * @since 2.0.0 */ import "./_dnt.polyfills.js"; import type { Kind, Out } from "./kind.js"; import type { Applicable } from "./applicable.js"; import type { Combinable } from "./combinable.js"; import type { Either } from "./either.js"; import type { Initializable } from "./initializable.js"; import type { Mappable } from "./mappable.js"; import type { Flatmappable } from "./flatmappable.js"; import type { Wrappable } from "./wrappable.js"; /** * A type for Promise over any, useful as an extension target for * functions that take any Promise and do not need to * unwrap the type. * @since 2.0.0 */ export type AnyPromise = Promise; /** * A type level unwrapor, used to pull the inner type from a Promise. * * @since 2.0.0 */ export type TypeOf = T extends Promise ? A : never; /** * Specifies Promise as a Higher Kinded Type, with * covariant parameter A corresponding to the 0th * index of any Substitutions. * * @since 2.0.0 */ export interface KindPromise extends Kind { readonly kind: Promise>; } /** * A Promise with the inner resolve function * hoisted and attached to itself. * * @since 2.0.0 */ export type Deferred = Promise & { readonly resolve: (a: A | PromiseLike) => void; }; /** * Create a Deferred from a type. * * @example * ```ts * import { deferred } from "./promise.ts"; * * const promise = deferred(); * * // Logs 1 after a second * promise.then(console.log); * setTimeout(() => promise.resolve(1), 1000); * ``` * * @since 2.0.0 */ export declare function deferred(): Deferred; /** * Make an existing Promise somewhat abortable. While * the returned promise does resolve when the abort signal * occurs, the existing promise continues running in the * background. For this reason it is important to * catch any errors associated with the original promise and * to not implement side effects in the aborted promise. * * @example * ```ts * import { abortable, wait } from "./promise.ts"; * import { pipe } from "./fn.ts"; * * const controller = new AbortController(); * const slow = wait(1000).then(() => 1); * const wrapped = pipe( * slow, * abortable(controller.signal, msg => msg), * ); * * setTimeout(() => controller.abort("Hi"), 500); * * // After 500ms result contains the following * // { tag: "Left", left: "Hi" } * const result = await wrapped; * ``` * * @since 2.0.0 */ export declare function abortable(signal: AbortSignal, onAbort: (reason: unknown) => B): (ua: Promise) => Promise>; /** * Create a Promise that resolve after ms milliseconds. * * @example * ```ts * import { wait, map } from "./promise.ts"; * import { pipe } from "./fn.ts"; * * const delayed = pipe( * wait(1000), * map(() => "Hello World"), * ); * * // After 1 second * const result = await delayed; // "Hello World" * ``` * * @since 2.0.0 */ export declare function wait(ms: number): Promise; /** * Delay the resolution of an existing Promise. This does not * affect the original promise directly, it only waits for * a ms milliseconds before flatmaping into the original promise. * * @example * ```ts * import { wrap, delay } from "./promise.ts"; * import { pipe } from "./fn.ts"; * * // Waits 250 milliseconds before returning * const result = await pipe( * wrap(1), * delay(250), * ); // 1 * ``` * * @since 2.0.0 */ export declare function delay(ms: number): (ua: Promise) => Promise; /** * An alias for Promise.resolve. * * @example * ```ts * import { resolve } from "./promise.ts"; * * const result = await resolve(1); // 1 * ``` * * @since 2.0.0 */ export declare function resolve(a: A | PromiseLike): Promise; /** * An alias for Promise.reject. * * @example * ```ts * import { reject } from "./promise.ts"; * * const result = await reject(1).catch(x => x); // 1 * ``` * * @since 2.0.0 */ export declare function reject(rejection: unknown): Promise; /** * An alias for Promise.then * * @example * ```ts * import { wrap, then } from "./promise.ts"; * import { pipe } from "./fn.ts"; * * const result = await pipe( * wrap(1), * then(n => n + 1), * ); // 2 * ``` * * @since 2.0.0 */ export declare function then(fai: (a: A) => I | Promise): (ua: Promise) => Promise; /** * An alias for Promise.catch * * @example * ```ts * import { reject, catchError } from "./promise.ts"; * import { pipe } from "./fn.ts"; * * const result = await pipe( * reject(1), * catchError(() => "Uhoh"), * ); // "UhOh" * ``` * * @since 2.0.0 */ export declare function catchError(fua: (u: unknown) => A): (ta: Promise) => Promise; /** * An alias for Promise.all * * @example * ```ts * import { all, wrap } from "./promise.ts"; * * const result = await all(wrap(1), wrap("Hello")); // [1, "Hello"] * ``` * * @since 2.0.0 */ export declare function all(...ua: T): Promise<{ [K in keyof T]: Awaited; }>; /** * An alias for Promise.race. Note that Promise.race leaks * async operations in most runtimes. This means that the * slower promise does not stop when the faster promise * resolves/rejects. In effect Promise.race does not * handle cancellation. * * @example * ```ts * import { wait, map, race, wrap } from "./promise.ts"; * import { pipe } from "./fn.ts"; * * const one = pipe(wait(200), map(() => "one")); * const two = pipe(wait(300), map(() => "two")); * * // After 200 milliseconds resolves from one * const result = await race(one, two); // "one" * ``` * * @since 2.0.0 */ export declare function race(...ua: T): Promise>; /** * Create a Promise from a value A or another PromiseLike. This * is essentially an alias of Promise.resolve. * * @example * ```ts * import { wrap } from "./promise.ts"; * * const result = await wrap(1); // 1 * ``` * * @since 2.0.0 */ export declare function wrap(a: A | PromiseLike): Promise; /** * Create a new Promise from a Promise<(a: A) => I> and * a Promise. Although Promises encapsulate * asynchrony, there is no way defer a Promise once created, * thus this ap function always evaluates both input Promises * in parallel. * * @example * ```ts * import { wrap, apply } from "./promise.ts"; * import { pipe } from "./fn.ts"; * * type Person = { name: string, age: number }; * * const person = (name: string) => (age: number): Person => ({ name, age }); * * const result = pipe( * wrap(person), * apply(wrap("Brandon")), * apply(wrap(37)), * ); // Promise * ``` * * @since 2.0.0 */ export declare function apply(ua: Promise): (ufai: Promise<(a: A) => I>) => Promise; /** * Create a new Promise by mapping over the result of an existing Promise. * This is effectively Promise.then, but narrowed to non-promise returning * functions. If the mapping function returns a Promise then the type * for this function will be incorrect, as there is no way to create a * Promise>. * * @example * ```ts * import { wrap, map } from "./promise.ts"; * import { pipe } from "./fn.ts"; * * const result = await pipe( * wrap(1), * map(n => n + 1), * ); // 2 * ``` * * @since 2.0.0 */ export declare function map(fai: (a: A) => I): (ua: Promise) => Promise; /** * Create a new Promise by flatmaping over the result of an existing Promise. * This is effectively Promise.then. * * @example * ```ts * import { wrap, flatmap } from "./promise.ts"; * import { pipe } from "./fn.ts"; * * const result = await pipe( * wrap(1), * flatmap(n => wrap(n + 1)), * ); // 2 * ``` * * @since 2.0.0 */ export declare function flatmap(faui: (a: A) => Promise): (ua: Promise) => Promise; /** * @since 2.0.0 */ export declare function fail(b: unknown): Promise; /** * Wrap a function that potentially throws in a try/catch block, * handling any thrown errors and returning the result inside * of a Promise. * * @example * ```ts * import { tryCatch, reject, wrap } from "./promise.ts"; * import { pipe, todo } from "./fn.ts"; * // Note that todo will always throw synchronously. * * const add = (n: number) => n + 1; * const throwSync = (_: number): number => todo(); * const throwAsync = (_: number): Promise => reject("Ha!"); * * const catchAdd = tryCatch(add, () => -1); * const catchSync = tryCatch(throwSync, () => -1); * const catchAsync = tryCatch(throwAsync, () => -1); * * const resultAdd = await catchAdd(1); // 2 * const resultSync = await catchSync(1); // -1 * const resultAsync = await catchAsync(1); // -1 * ``` * @since 2.0.0 */ export declare function tryCatch(handle: (...args: D) => A | PromiseLike, onThrow: (error: unknown, args: D) => A): (...args: D) => Promise; /** * @since 2.0.0 */ export declare function getCombinablePromise({ combine }: Combinable): Combinable>; /** * @since 2.0.0 */ export declare function getInitializablePromise(I: Initializable): Initializable>; /** * The canonical implementation of Applicable for Promise. It contains * the methods wrap, apply, and map. * * @since 2.0.0 */ export declare const ApplicablePromise: Applicable; /** * The canonical implementation of Mappable for Promise. It contains * the method map. * * @since 2.0.0 */ export declare const MappablePromise: Mappable; /** * The canonical implementation of Flatmappable for Promise. It contains * the methods wrap, apply, map, and flatmap. * * @since 2.0.0 */ export declare const FlatmappablePromise: Flatmappable; /** * @since 2.0.0 */ export declare const WrappablePromise: Wrappable; /** * @since 2.0.0 */ export declare const tap: (fn: (value: A) => void) => (ua: Promise) => Promise; /** * @since 2.0.0 */ export declare const bind: (name: Exclude, faui: (a: A) => Promise) => (ua: Promise) => Promise<{ readonly [K_1 in N | keyof A]: K_1 extends keyof A ? A[K_1] : I; }>; /** * @since 2.0.0 */ export declare const bindTo: (name: N) => (ua: Promise) => Promise<{ readonly [K in N]: A; }>;