type PromiseFulfillFunc = (val: T) => void; type PromiseThenFunc = (val: T) => NextT; type PromiseRejectFunc = (err: unknown) => void; type PromiseFunc = (resolve: PromiseFulfillFunc, reject: PromiseRejectFunc) => void; type PromiseResult ={ type: 'fulfilled'; value: T; } | { type: 'rejected'; reason: any; } interface Thenable { then(this: Promise, onFulfilled: PromiseThenFunc, onRejected?: PromiseRejectFunc): Promise>; then(this: Promise, onFulfilled: undefined, onRejected?: PromiseRejectFunc): Promise; } // wippidy-wine, this code is now mine :D type Awaited = T extends null | undefined ? T : // special case for `null | undefined` when not in `--strictNullChecks` mode T extends object & { then(onfulfilled: infer F, ...args: infer _): any } ? // `await` only unwraps object types with a callable `then`. Non-object types are not unwrapped F extends ((value: infer V, ...args: infer _) => any) ? // if the argument to `then` is callable, extracts the first argument Awaited : // recursively unwrap the value never : // the argument to `then` was not callable T; interface PromiseConstructor { prototype: Promise; new (func: PromiseFunc): Promise>; resolve(val: T): Promise>; reject(val: any): Promise; any(promises: (Promise|T)[]): Promise; race(promises: (Promise|T)[]): Promise; all(promises: T): Promise<{ [Key in keyof T]: Awaited }>; allSettled(...promises: T): Promise<[...{ [P in keyof T]: PromiseResult>}]>; } interface Promise extends Thenable { constructor: PromiseConstructor; catch(func: PromiseRejectFunc): Promise; finally(func: () => void): Promise; } declare var Promise: PromiseConstructor; (Promise.prototype as any)[Symbol.typeName] = 'Promise';