Wrote a library that, depending on the input data; creates classes and uses them inside a main class.
To make the code more maintainable and readable, I've moved the class generation logic into a separate file that exports a factory function.
Code was written in ES2015. Now I'm migrating to TypeScript.
Here is a pseudo example:
export default function (foo:string) => {
class A {
value:string = foo + '-A';
}
return { A };
};
import factory from './factory';
export default class Main {
private inner:any;
constructor(foo:string) {
this.inner = factory(foo);
}
get a() {
return new this.inner.A();
}
}
let main = new Main('bar');
console.log(main.a.value); // "bar-A"
Default export of the module has or is using private name 'A'.
a
as A
in Main
class (e.g. get a():A { ... }
How would you resolve this (keeping the factory classes in a separate file)? Or should I change the design pattern?
How about something like:
export interface Base {}
export interface IA extends Base {
value: string;
}
export type Builders = {
[name: string]: { new <T extends Base>(): T };
}
export function factory(foo: string): Builders {
class A implements IA {
value:string = foo + '-A';
}
return { A };
};
And:
import { factory, IA, Builders } from './Factory';
export default class Main {
private inner: Builders;
constructor(foo:string) {
this.inner = factory(foo);
}
get a():IA {
return new this.inner.A() as IA;
}
}
What's wrong with this as factory.ts
:
export class Base {}
export type Builders = {
[name: string]: { new <T extends Base>(): T };
}
class A extends Base {
value: string;
constructor();
constructor(foo: string);
constructor(foo?: string) {
super();
this.value = foo + "-A";
}
}
// more classes...
export function factory(foo: string): Builders {
return { A: A.bind(A, foo) };
};
It's basically the same as what you did, just that the classes are not defined inside the class, and are exported so no need for the interfaces I suggested.
Also, this way all the classes will only be evaluated once and not every time the factory
function is invoked.
Your code (the OP's) is working just fine in July 2019 with Typescript 3.5.2.
PS. I got here when I was trying to create a Class Factory in Typescript.
Things to keep in mind:
type classType = InstanceType<typeof C>
. This should make the explicit type
definition in the selected answer simpler.export default class MyNewClass
extends ClassFactory("custom param1") {}
This way I am actually defining the generated class as a new class by itself, so both the constructor function and the instance-type type are going to be implicitly created and will be valid. And I don't need to explicitly define the two separately.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With