@synstack/resolved
Version:
Type-safe piping of synchronous or asynchronous values
66 lines (64 loc) • 2.7 kB
text/typescript
type Resolvable<T> = Promise<T> | T;
declare namespace Resolvable {
type Infer<T> = Awaited<T>;
type IsPromise<T> = T extends Promise<any> ? true : never;
type ArrayOf<T> = Array<Resolvable<T>>;
namespace ArrayOf {
type Infer<T> = T extends readonly any[] ? {
[K in keyof T]: Resolvable.Infer<T[K]>;
} : never;
type HasPromise<T> = T extends readonly any[] ? {
[K in keyof T]: Resolvable.IsPromise<T[K]>;
}[number] : never;
}
type MaybeArray<T> = Resolvable.ArrayOf<T> | Resolvable<T>;
namespace MaybeArray {
type Infer<T> = T extends readonly any[] ? {
[K in keyof T]: Resolvable.Infer<T[K]>;
} : Resolvable.Infer<T>;
type IsPromise<T> = T extends readonly any[] ? {
[K in keyof T]: Resolvable.IsPromise<T[K]>;
}[number] : Resolvable.IsPromise<T>;
}
}
/**
* Resolves all values in the array in parallel
* @param value The array to resolve
* @returns If the array contains promises, a promise of an array of values. Otherwise, the array.
*/
declare const resolveAll: <U extends readonly any[]>(value: U) => true extends Resolvable.ArrayOf.HasPromise<U> ? Promise<Resolvable.ArrayOf.Infer<U>> : U;
declare class Resolver<T extends Resolvable<any>> {
private readonly _value;
constructor(value: T);
/**
* Get the value of the resolver
* @returns The value or a single promise of the value
*
* - If the value is an array containing promises, the array will be resolved with `Promise.all`
*/
get $(): T extends readonly any[] ? true extends Resolvable.ArrayOf.HasPromise<T> ? Promise<Resolvable.ArrayOf.Infer<T>> : T : T;
valueOf(): T;
/**
* Apply a function to the value
* @param fn the function to apply to the value
* @returns a new Resolver instance with the result of the function, either a value or a promise of a value
*/
_<R>(fn: (value: Resolvable.MaybeArray.Infer<T>) => R): true extends Resolvable.MaybeArray.IsPromise<T> ? true extends Resolvable.MaybeArray.IsPromise<R> ? Resolver<R> : Resolver<Promise<R>> : Resolver<R>;
}
/**
* A piping utility which preserves the sync/async state of the value
* @param value The value to pipe
* @returns A new Resolver instance
*
* ```ts
* import { pipe } from "@synstack/resolved";
*
* // Sync
* const value: string = pipe("Hello World")._((v) => v.toUpperCase()).$;
*
* // Async
* const promiseValue: Promise<string> = pipe("Hello World")._((v) => Promise.resolve(v.toUpperCase())).$;
* ```
*/
declare const pipe: <T>(value: T) => Resolver<T>;
export { Resolver as R, Resolvable as a, pipe as p, resolveAll as r };