src/vs/base/common/worker/simpleWorker.ts/createProxyMethod
function createProxyObject<T extends object>(
	methodNames: string[],
	invoke: (method: string, args: unknown[]) => unknown,
	proxyListen: (eventName: string, arg: any) => Event<any>
): T {
	const createProxyMethod = (method: string): () => unknown => {
		return function () {
			const args = Array.prototype.slice.call(arguments, 0);
			return invoke(method, args);
		};
	};
	const createProxyDynamicEvent = (eventName: string): (arg: any) => Event<any> => {
		return function (arg) {
			return proxyListen(eventName, arg);
		};
	};

	const result = {} as T;
	for (const methodName of methodNames) {
		if (propertyIsDynamicEvent(methodName)) {
			(<any>result)[methodName] = createProxyDynamicEvent(methodName);
			continue;
		}
		if (propertyIsEvent(methodName)) {
			(<any>result)[methodName] = proxyListen(methodName, undefined);
			continue;
		}
		(<any>result)[methodName] = createProxyMethod(methodName);
	}
	return result;
}