Skip to content

Commit

Permalink
feat: Add typed composition stacking support
Browse files Browse the repository at this point in the history
  • Loading branch information
iainjreid committed Jul 31, 2022
1 parent 7e471cd commit 44751fe
Show file tree
Hide file tree
Showing 8 changed files with 228 additions and 85 deletions.
72 changes: 46 additions & 26 deletions lib/compose.d.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,61 @@
export declare type ComposableTarget<C1, I1 extends any[], R1, E1> =
CallableFunction & ((this: C1, ...args: I1) => Promise<R1, E1>);
import { Promise } from "./promise";

export declare type ComposableFunction<C1, I1 extends any[], R1, E1> =
((this: C1, ...args: I1) => Promise<R1, E1>);

/**
* If you see this error message when building your code, it's likely that
* you're adding a function to a composition that is destined to fail.
*/
export type UnreachableFunctionWarning = "Your function will never be run";

export declare type ComposableSafeFunction<C1, R1, R2> =
[R1] extends [never] ? UnreachableFunctionWarning : ((this: C1, val: R1) => R2 | Promise<R2, never>)
export declare type SafeComposableFunction<C1, R1, R2> =
[R1] extends [never]
? UnreachableFunctionWarning
: ComposableFunction<C1, [R1], R2, never>;

export declare type ComposableUnsafeFunction<C1, R1, R2, E1 = unknown> =
[R1] extends [never] ? UnreachableFunctionWarning : ((this: C1, val: R1) => Promise<R2, E1>)
export declare type UnsafeComposableFunction<C1, R1, R2, E1> =
[R1] extends [never]
? UnreachableFunctionWarning
: ComposableFunction<C1, [R1], R2, E1>;

export interface SafeComposable<C1, I1 extends any[], R1> extends ComposableTarget<C1, I1, R1, never> {
then<R2, E1, C2 extends C1 = C1>(fn: ComposableUnsafeFunction<C2, R1, R2, E1>):
[E1] extends [never] ? never : UnsafeComposable<C2, I1, R2, E1>;
/**
*
*/
export interface SafeComposition<C1, I1 extends any[], R1> extends ComposableFunction<C1, I1, R1, never> {
then<R2, __, C2 extends C1 = C1>(fn: SafeComposableFunction<C2, R1, R2>):
SafeComposition<C2, I1, R2>;

then<R2, __, C2 extends C1 = C1>(fn: ComposableSafeFunction<C2, R1, R2>):
SafeComposable<C2, I1, R2>;
then<R2, E1, C2 extends C1 = C1>(fn: UnsafeComposableFunction<C2, R1, R2, E1>):
UnsafeComposition<C2, I1, R2, E1>;

catch: never;
catch<__, C2 extends C1 = C1>(fn: SafeComposableFunction<C2, never, R1>): never;
}

export interface UnsafeComposable<C1, I1 extends any[], R1, E1> extends ComposableTarget<C1, I1, R1, never> {
__ErrorTypeCheck__: [E1] extends [never] ? 'Please use a "SafeComposable"' : E1;

then<R2, E2, C2 extends C1 = C1>(fn: ComposableUnsafeFunction<C2, R1, R2, E2>):
UnsafeComposable<C2, I1, R2, E1 | E2>;
/**
*
*/
export interface UnsafeComposition<C1, I1 extends any[], R1, E1> extends ComposableFunction<C1, I1, R1, E1> {
then<R2, __, C2 extends C1 = C1>(fn: SafeComposableFunction<C2, R1, R2>):
UnsafeComposition<C2, I1, R2, E1>;

then<R2, __, C2 extends C1 = C1>(fn: ComposableSafeFunction<C2, R1, R2>):
UnsafeComposable<C2, I1, R2, E1>;
then<R2, E2, C2 extends C1 = C1>(fn: UnsafeComposableFunction<C2, R1, R2, E2>):
UnsafeComposition<C2, I1, R2, E1 | E2>;

catch<E2, C2 extends C1 = C1>(fn: ComposableUnsafeFunction<C2, E1, R1, E2>):
[E2] extends [never] ? never : UnsafeComposable<C2, I1, R1, E2>;
catch<__, C2 extends C1 = C1>(fn: SafeComposableFunction<C2, E1, R1>):
SafeComposition<C2, I1, R1>;

catch<__, C2 extends C1 = C1>(fn: ComposableSafeFunction<C2, E1, R1>):
SafeComposable<C2, I1, R1>;
catch<E2, C2 extends C1 = C1>(fn: UnsafeComposableFunction<C2, E1, R1, E2>):
UnsafeComposition<C2, I1, R1, E2>;
}

export declare function compose<C1, I1 extends any[], V1, E1 = never>(fn: ComposableTarget<C1, I1, V1, E1>):
export declare function resolve<T>(val: T): Promise<T, never>;
export declare function resolve(): Promise<void, never>;

export declare function reject<T>(val: T): Promise<never, T>;
export declare function reject(): Promise<never, void>;

export declare function compose<C1, I1 extends any[], R1, E1>(fn: ComposableFunction<C1, I1, R1, E1>):
[E1] extends [never]
? SafeComposable<C1, I1, V1>
: UnsafeComposable<C1, I1, V1, E1>;
? SafeComposition<C1, I1, R1>
: UnsafeComposition<C1, I1, R1, E1>;
5 changes: 3 additions & 2 deletions lib/compose.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*
* @param fn - The function to compose
*/
function compose(fn) {
export function compose(fn) {
return Object.setPrototypeOf(function (...args) {
return fn.apply(this, args);
}, compose);
Expand All @@ -26,4 +26,5 @@ compose.catch = function (fn) {
});
}

exports.compose = compose;
export const resolve = Promise.resolve.bind(Promise);
export const reject = Promise.reject.bind(Promise);
Loading

0 comments on commit 44751fe

Please sign in to comment.