I'm trying to have a class which partly acts as a Proxy wrapper around some other class, allowing the other class methods to be modified and accept either extra arguments or to change their type.
Let's imagine I have:
class MainClass {
myMethod(txt: string) {}
unrelatedProp = "a prop that's not a method"
}
I want to have a class that would look something like this:
class MyHelper {
mainClass: MainClass;
// ... this does a bunch of other stuff not related to `MainClass`
}
const main = new MainClass();
const helper = new MyHelper(main);
helper.myMethod(2) // ← I want to extend `myMethod` to accept, for example, `string | number`.
Firstly, I'm not sure if this is even a thing and there is a better way than using Proxy to do this, but I'm doing this:
type ExtendFirstParamType<T extends (...args: any[]) => any, U> = [
Parameters<T>[0] | U,
...Parameters<T>
]
// ^^^ First problem here:
// 1. I'll be able to use this type to only extend the first parameter,
// it'd be nice to create a generic which would extend at any index
// 2. I'd need to splice/shift the parameter, instead here I'm spreading
// the rest of the parameters, so I'll get the first parameter again.
class MyHelper {
constructor(public mainClass: MainClass) {
const handler = {
get(target: MainClass, propKey: keyof MainClass) {
const property = target[propKey];
if(typeof property !== "function") return property;
else {
return (...args: ExtendFirstParamType<typeof property, number>) => {
// ^^^ Here you can see by hovering that the type is on the right track
// it correctly infers that the first argument is now `string | number`
return property.apply(this, args as any);
}
}
}
}
this.mainClass = new Proxy(page, handler);
// ^^^ How would I make sure that this type would be the proxied/extended
// class? If I don't declare it in my class it complains that it doesn't exist
// but if I declare it, and type it as `MainClass`, `myMethod` would not have
// the new proxied type signature
}
}
Here is a Typescript playground link with what I have so far.