import {AxiosResponse} from 'axios'; class BadResponseError extends Error { constructor(public err: Error, public res: AxiosResponse) { super(err.toString()); Object.setPrototypeOf(this, BadResponseError.prototype); } } type Optional = T | undefined | null; type TPromiseOn = Optional<(_: T) => R | PromiseLike>; export abstract class APIPromise implements PromiseLike { promise: Promise; constructor(req: Promise>) { this.promise = new Promise((rsv, rjt)=>{ req.then(res=>{ try { rsv(this.onResponse(res)); } catch (err) { rjt(new BadResponseError(err, res)); } }).catch(err=>rjt(err)); }); } then(onRsv?: TPromiseOn, onRjt?: TPromiseOn) { return this.promise.then(onRsv, onRjt); } catch(onRjt: TPromiseOn) { return this.then(undefined, onRjt); } abstract onResponse(res: AxiosResponse): T; onSuccess(f: Optional<(x: U)=>V>, v: U): U | V { if (f) return f(v); else return v; } onFail(f: Optional<(x: U)=>V>, v: U) { if (f) return f(v); else throw new Error(); } }