Working in a factory setting, I find myself needing to incorporate custom methods at some point.
Thanks to the valuable input from the community, I've made progress towards my goal with this helpful answer, although I'm required to include a seemingly unnecessary argument for it to function as intended.
Below is an adjusted version of the code based on the aforementioned solution.
type Base = { id: string }
type Factory<E> = new () => E;
function factory<E extends Base>(name: string): Factory<E>;
function factory<E extends Base, M extends Record<string, <S extends M>(this: E & S) => unknown>>(
name: string, methods: M, useless?: (this: E & M) => void
): Factory<E & M>;
function factory<E extends Base, M extends Record<string, <S extends M>(this: E & S) => unknown>>(
name: string, methods?: M, useless?: (this: E & M) => void
): Factory<E> {
const ret = function(this: Base) {
this.id = "0"
};
Object.defineProperty(ret, "name", { value: name });
if(methods) Object.assign(ret.prototype, methods);
return ret as unknown as Factory<E>;
}
const T2 = factory(
"T2",
{
test: function(repeat = true) {
if(repeat) this.test(false);
return "test";
}
},
function() {} // If we comment out this line, the TypeScript magic breaks (but not the JavaScript one)
);
const t2 = new T2();
console.log(t2, t2.id, t2.test());
Removing the useless
argument disables the visibility of the test
method within its definition!
Any thoughts on how to address this issue without relying on the presence of the useless
argument?
Feel free to explore and experiment using this interactive playground.