I am building a class system in Typescript. There is a main abstract class Component
, that has a static method create()
. This method will be called on children to build a particular instance
abstract class Component {
static build() {
// some additional logic here, for example, cache to reuse instances
return new this();
}
}
class Button extends Component { }
class Input extends Component {}
Button.build(); // returns Button instance
Input.build(); // returns Input instance
Same code in TS Playground
This approach works well in Javascript, but Typescript reports an error at the line new this()
, saying "Cannot create an instance of an abstract class."
How can I explain typescript that method will be called on derived instances, but not on the main abstract class directly? Maybe there are other ways to implement the API that I needed?
Short answer: Yes. Actually, since Java 8 you can provide default implementations for the methods in an interface and the only differences to an abstract class are constructors (which you don't use anyway apparently) and fields which should be private, so there's very little difference.
A static method belongs to class not to object instance thus it cannot be overridden or implemented in a child class. So there is no use of making a static method as abstract.
Abstract Factory classes are often based on a set of Factory Methods, but you can also use Prototype to compose the methods on these classes. Abstract Factory can serve as an alternative to Facade when you only want to hide the way the subsystem objects are created from the client code.
A static factory method is a public static method on the object that returns a new instance of the object. These type of methods share the same benefits as the traditional factory method design pattern. This is especially useful for value objects that don't have a separate interface and implementation class.
this
is typeof Component
, and since Component
is abstract class, new this
is inadmissible. Even if Component
wasn't abstract, Button.build()
return type wouldn't be properly handled in child classes.
It requires some type hinting, via generic method:
abstract class Component {
static build<T = Component>(this: { new(): T }) {
return new this();
}
}
class Button extends Component { }
const button = Button.build<Button>(); // button: Button
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