export type ControllablePromise = Promise & { resolve(val: T): void reject(err?: unknown): void } export type CancellablePromise = Promise & { cancel(): void } export class PromiseCancelledError extends Error {} export function createControllablePromise(): ControllablePromise { let _resolve: any let _reject: any const promise = new Promise((resolve, reject) => { _resolve = resolve _reject = reject }) ;(promise as ControllablePromise).resolve = _resolve ;(promise as ControllablePromise).reject = _reject return promise as ControllablePromise } export function createCancellablePromise( onCancel: () => void ): ControllablePromise & CancellablePromise { const promise = createControllablePromise() ;(promise as unknown as CancellablePromise).cancel = () => { promise.reject(new PromiseCancelledError()) onCancel() } return promise as ControllablePromise & CancellablePromise }