Web components are probably our best bet to end our dependency on overly large Javascript frameworks, but they have a few weaknesses that I've run into. Constructors, on their own, are a bit useless. When working on a Typescript web component, I wanted to initialize some private readonly fields based on its child elements or HTML attributes only to find that they are not guaranteed to exist when the constructor runs: they need to be declared as mutable (i.e: no readonly) and optional (i.e: ?) since non-optional members which are undefined in the constructor generate errors in typescript. This kind of ruins the class-based aspect of web component integration with typescript.
However, constructors are good for one thing: dependency injection. I've seen a few blog posts from people who have developed a length sort of dependency injection framework with factories and scoped/singleton dependency injection which mirrors frameworks like Angular, but I've been using a more Javascript-idiomatic technique that works very well for me and is quite lightweight. Since classes are sort-of-types, sort-of-objects in Javascript, they can be defined inline when registering a web component. Consider the following web component in typescript:
And that's it! In my webpack projects I define an index.prod.ts and an index.mock.ts for production vs demo purposes, and inject Mock services from this entrypoint when registering my web components. You then use the web component like this: