Skip to content

Instantly share code, notes, and snippets.

@jbr
Last active December 4, 2019 20:48
Show Gist options
  • Save jbr/f13263fcfa37e6efa1ef942a780b7682 to your computer and use it in GitHub Desktop.
Save jbr/f13263fcfa37e6efa1ef942a780b7682 to your computer and use it in GitHub Desktop.
An attempt at a type-aware promise wrapper
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function existingFunction(promise, property) {
return (...args) => buildProxy(promise[property].apply(promise, args));
}
function buildProxy(promiseOrValue) {
const promise = "then" in promiseOrValue ? promiseOrValue : Promise.resolve(promiseOrValue);
return new Proxy(promise, {
get(target, property) {
if (property in promise)
return existingFunction(promise, property);
return (...args) => buildProxy(new Promise(resolve => target.then(m => {
const method = m[property];
const results = method.apply(m, args);
resolve(results);
})));
}
});
}
exports.default = buildProxy;
type ProxiedDynamic<T> = {
[K in FunctionKeys<T>]: (
...args: Parameters<T[K]>
) => Proxied<ReturnType<T[K]>>;
};
type Proxied<T> = ProxiedDynamic<T> & Promise<T>;
type FunctionKeys<T> = {
[K in keyof T & string]: T[K] extends (...args: any[]) => any ? K : never;
}[keyof T & string];
function existingFunction<T, U extends keyof Promise<T>>(
promise: Promise<T>,
property: U
) {
return (...args: Parameters<Proxied<T>[U]>) =>
buildProxy(promise[property].apply(promise, args));
}
export default function buildProxy<T>(
promiseOrValue: Promise<T> | T
): Proxied<T> {
const promise =
"then" in promiseOrValue ? promiseOrValue : Promise.resolve(promiseOrValue);
return new Proxy(promise, {
get<V, W extends FunctionKeys<V>>(target: Promise<V>, property: W) {
if (property in promise)
return existingFunction(
promise,
(property as unknown) as keyof typeof promise
);
return (...args: Parameters<V[W]>) =>
buildProxy(
new Promise<ReturnType<V[W]>>(resolve =>
target.then(m => {
const method = m[property] as (
...args: Parameters<V[W]>
) => ReturnType<V[W]>;
const results = method.apply(m, args);
resolve(results);
})
)
);
}
}) as Proxied<T>;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment