I find myself in a bit of a dilemma.
The class I have is within my control for modifications, but it needs to be dynamically instantiated by an external code that I have no authority over. Unfortunately, this code cannot pass generic type arguments to the constructor, which necessitates that the constructor arguments must strictly be plain data (such as JSON serializable). Furthermore, this class contains a property that requires an instance of another class (that I do not have any influence on) with a generic type argument that is a subset of a union type and function arguments which I would prefer to lazily instantiate due to these restrictions.
In essence, I am tasked with acting as a liaison between two disparate pieces of unmodifiable code.
Here's a simplified example:
type ABC = 'a' | 'b' | 'c';
// Foo is beyond my control.
class Foo<T extends ABC> {
foo (x: T): void {
console.log(x.repeat(2))
}
}
// Bar itself cannot be generic, as explained in the scenario.
// While I can tweak the implementation of Bar, Foo or the code
// instantiating Bar remain off-limits.
class Bar {
foo?: Foo; // <-- Issue lies here
// I retain control over the code calling this method
createFoo<T extends ABC>(): void {
this.foo = new Foo<T>()
}
}
When used independently, Foo
performs as expected:
const test1 = new Foo<'b' | 'c'>();
test1.foo('a'); // appropriately errors out
I attempted to utilize the union itself as a placeholder...
class Baz {
foo?: Foo<ABC>
createFoo<T extends ABC>(): void {
this.foo = new Foo<T>()
}
}
However, this led to:
const bz = new Baz();
bz.createFoo<'b' | 'c'>();
bz.foo?.foo('a') // Oops! This should fail just like in the initial example.
Is there a viable way to resolve this conundrum? I acknowledge these constraints are quite peculiar, but unfortunately, they are non-negotiable.