Skip to content

Instantly share code, notes, and snippets.

@erwinv
Last active July 18, 2022 02:59
Show Gist options
  • Save erwinv/71afcebfb47678dd8b64342f2973f86c to your computer and use it in GitHub Desktop.
Save erwinv/71afcebfb47678dd8b64342f2973f86c to your computer and use it in GitHub Desktop.
TypeScript Variadic Tuples for typing `promisify`
type Tuple<T=any> = readonly T[]
type Nullable<T> = T extends null | undefined ? T : T | null | undefined
type ErrorFirstCallback<E extends Error, R> = (err: Nullable<E>, result: R) => void
type Resolve<R> = (value: R | PromiseLike<R>) => void
type Reject<E extends Error> = (reason: Nullable<E>) => void
function makeCallback<E extends Error, R>(resolve: Resolve<R>, reject: Reject<E>): ErrorFirstCallback<E, R> {
return (error, result) => {
if (error) reject(error)
else resolve(result)
}
}
export function promisify<Args extends Tuple, E extends Error, R>(fn: (...args: [...Args, ErrorFirstCallback<E, R>]) => void) {
return function promisifiedFn(...args: Args) {
return new Promise<R>((resolve, reject) => {
const cb = makeCallback<E, R>(resolve, reject)
try {
fn(...args, cb)
} catch(e) {
reject(e)
}
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment