interface Function { apply(this: Function, thisArg: any, argArray?: any): any; call(this: Function, thisArg: any, ...argArray: any[]): any; bind(this: Function, thisArg: any, ...argArray: any[]): Function; toString(): string; prototype: any; constructor: FunctionConstructor; readonly length: number; name: string; } interface FunctionConstructor extends Function { (...args: string[]): (...args: any[]) => any; new (...args: string[]): (...args: any[]) => any; prototype: Function; async( func: (await: (val: T) => Awaited) => (...args: ArgsT) => RetT ): (...args: ArgsT) => Promise; asyncGenerator( func: (await: (val: T) => Awaited, _yield: (val: T) => void) => (...args: ArgsT) => RetT ): (...args: ArgsT) => AsyncGenerator; generator( func: (_yield: (val: T) => TNext) => (...args: ArgsT) => RetT ): (...args: ArgsT) => Generator; } interface CallableFunction extends Function { (...args: any[]): any; apply(this: (this: ThisArg, ...args: Args) => RetT, thisArg: ThisArg, argArray?: Args): RetT; call(this: (this: ThisArg, ...args: Args) => RetT, thisArg: ThisArg, ...argArray: Args): RetT; bind(this: (this: ThisArg, ...args: [ ...Args, ...Rest ]) => RetT, thisArg: ThisArg, ...argArray: Args): (this: void, ...args: Rest) => RetT; } interface NewableFunction extends Function { new(...args: any[]): any; apply(this: new (...args: Args) => RetT, thisArg: any, argArray?: Args): RetT; call(this: new (...args: Args) => RetT, thisArg: any, ...argArray: Args): RetT; bind(this: new (...args: Args) => RetT, thisArg: any, ...argArray: Args): new (...args: Args) => RetT; } declare var Function: FunctionConstructor; gt.Function = function() { throw 'Using the constructor Function() is forbidden.'; } as unknown as FunctionConstructor; Function.prototype = (Function as any).__proto__ as Function; setConstr(Function.prototype, Function); setProps(Function.prototype, { apply(thisArg, args) { if (typeof args !== 'object') throw 'Expected arguments to be an array-like object.'; var len = args.length - 0; let newArgs: any[]; if (Array.isArray(args)) newArgs = args; else { newArgs = []; while (len >= 0) { len--; newArgs[len] = args[len]; } } return internals.apply(this, thisArg, newArgs); }, call(thisArg, ...args) { return this.apply(thisArg, args); }, bind(thisArg, ...args) { var func = this; var res = function() { var resArgs = []; for (var i = 0; i < args.length; i++) { resArgs[i] = args[i]; } for (var i = 0; i < arguments.length; i++) { resArgs[i + args.length] = arguments[i]; } return func.apply(thisArg, resArgs); }; res.name = " " + func.name; return res; }, toString() { return 'function (...) { ... }'; }, }); setProps(Function, { async(func: (_yield: (val: T) => Awaited) => (...args: ArgsT) => RetT) { if (typeof func !== 'function') throw new TypeError('Expected func to be function.'); return function (this: any) { const args = arguments; return new Promise((res, rej) => { const gen = Function.generator(func as any).apply(this, args as any); (function next(type: 'none' | 'err' | 'ret', val?: any) { try { let result; switch (type) { case 'err': result = gen.throw(val); break; case 'ret': result = gen.next(val); break; case 'none': result = gen.next(); break; } if (result.done) res(result.value); else Promise.resolve(result.value).then( v => next('ret', v), v => next('err', v) ) } catch (e) { rej(e); } })('none'); }); }; }, generator(func) { if (typeof func !== 'function') throw new TypeError('Expected func to be function.'); return internals.makeGenerator(func); } })