Unable to designate a 'restricted' constructor type as a 'public' constructor type

I devised an abstract base class that facilitates asynchronous instantiation to load data before returning the instance. My goal is to prevent users from utilizing the constructor to avoid accessing an uninitialized instance, but I encountered the subsequent error when attempting to make the constructor protected:

The 'this' context of type 'typeof InheritedController' cannot be assigned to the method's 'this' type of 'Constructor'. It is not possible to assign a 'protected' constructor type to a 'public' constructor type.

This snippet showcases my code:

type Constructor<T> = new () => T;

export default abstract class BaseController {
  static async create<T extends BaseController>(
    this: Constructor<T>
  ): Promise<T> {
    const controller = new this();
    await controller.initialize();
    return controller;
  }

  protected constructor() {}

  protected async initialize() {
    console.log('Initializing asynchronously...');
  }
}

class InheritedController extends BaseController {
  protected async initialize(): Promise<void> {
    // Perform data loading process
  }
}

const controller = await InheritedController.create()

I am puzzled by this error message and have yet to discover a viable solution.

Answer №1

It is not advisable to make the constructor and the initialize methods protected. It's better to keep them public. Instead, modify the constructor and its signature so that an uninitialized instance cannot be created! Pass all the required data as arguments. You can maintain the static create function by making a small change in the pattern:

interface ControllerConstructor<T, C> {
  new (options: T): C;
  initOptions(): Promise<T>;
}

export default abstract class BaseController<T> {
  static async create<T, C extends BaseController<T>>(this: ControllerConstructor<T, C>): Promise<C> {
    return new this(await this.initOptions());
  }
  constructor(options: T) {}
}

class InheritedController extends BaseController<void> {
  static async initOptions(): Promise<void> {
    // await loading data
  }
}

const newController = await InheritedController.create()

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Generating duplicate elements conditionally in Typescript

One of the functionalities in my application involves a variable that users can adjust, for example: let myValue = 3; What I want to accomplish is to generate multiple duplicates of an element in my HTML based on the value of this variable. For instance ...

The Vue application encountered an issue while trying to mount the component due to the absence of a defined template or render function. The error was triggered

Here is the code snippet for my component: <template> <uploader class="uploader-example"> <uploader-unsupport></uploader-unsupport> <uploader-drop> <p>Drop ...

AngularJS - Sending event to a specific controller

I am facing an issue with my page where a list of Leads each have specific actions that are represented by forms. These forms can be displayed multiple times on the same page. Each form has its own scope and controller instance. After submitting a form, an ...

Enhancing the API response with Typescript interfaces for complex nested objects

Just stepping into the world of Typescript and attempting to introduce types to a basic application. Struggling with an error related to a deeply nested object. export default function AnimalAdoptionCosts() { const [currencyQuote, setCurrencyQuote] = use ...

Preserving the value of a function argument for future reference

I have a function called myFunction() that accepts one argument. My goal is to save this argument to a variable and be able to access it later. Here is what I am attempting to do: When a user performs an action, an event is passed as an argument to the m ...

Creating a JSON array or JSON object from an Angular Material table

My task is to create a JSON array or object from an Angular Material table, which I can then utilize to export to an Excel sheet. Here is the data: const ELEMENT_DATA: Element[] = [ {position: 1, name: 'Hydrogen', weight: 1.0079, symbol: &apo ...

Having trouble with an unexpected value in your Angular2 Service? Don't forget to add

I encountered an error in my Angular2 app: Error: (SystemJS) Unexpected value 'ReleasesService' declared by the module 'AppModule'. Please add a @Pipe/@Directive/@Component annotation. Here is my AppModule code: import { NgModule } fr ...

Transform a dynamic JSON configuration into a Typescript class

After extensively searching the web, reading through typescript documents, and reviewing numerous responses here on stack overflow, I have yet to find a solution that fully addresses my query: In my typescript code, I import a JSON file with the following ...

Drizzle ORM retrieve unique string that is not a database column

I'm working with a SQL query that looks like this: SELECT * FROM ( SELECT 'car' AS type, model FROM car UNION SELECT 'truck' AS type, model FROM trucks ) vehicles; In Drizzle, I'm trying to replicate the 'car ...

Encountered an error while attempting to load module script

Upon launching an Angular application on Heroku, a situation arises where accessing the URL displays a blank page and the console reveals MIME type errors. The error message reads: "Failed to load module script: The server responded with a non-JavaScrip ...

When the nestjs interface appears to be missing a defined method

Upon reviewing the code at this link: https://github.com/nestjs/nest/tree/master/packages/common One can see that the interface ArgumentsHost has been defined, but the contents of its methods are not explicitly defined. However, when looking at the foll ...

Assign a specific value to each object

Receiving data from the backend in a straightforward manner: this.archiveService.getRooms(team).subscribe( res => { this.form = res; this.form.forEach(el => { el.reservation.slice(-6).match(/.{1,2}/g).join('/'); }); }, ...

Creating aliases for routes in Angular

In my Angular 6 application, I am exploring the process of creating URL aliases. However, I have encountered a roadblock that I hope you can help me with: In my angular app, I currently have a URL defined as article/:id, which corresponds to the Articl ...

Learn the correct way to export a React class component with proper type declarations

Encountering an issue when exporting a React class component for use in Enzyme, as it is exporting as a function type: class MyComponent extends React.Component<MyComponentProps, MyComponentState> { ... } export default connect(null, mapDispatchToP ...

Getting rid of the unclear warning? The value obtained from traversing Object.entries must be a string and ensure

After successfully compiling and running my code, I noticed that my Typescript editor is still giving a warning for val in line 57. You can view the code on the Playground Link. for (const [key, val] of Object.entries(searchInvocation)) { encoded ...

Utilize the super type as a generic parameter in TypeScript for stronger assertions

The Query Within TypeScript, utilizing the keyword extends allows for asserting a generic parameter as a 'subtype' of another type. For example: // class Base {} // class Child extends Base {} // edited: class Base { a = 1 } class Child extends ...

Incorporating a unique variant with Tailwind called "

I'm currently struggling with inputting the configuration file for Tailwind. Despite my efforts, I cannot seem to get it right. The code appears correct to me, but I am unsure of what mistake I might be making. Below is the snippet of my code: import ...

What is the significance of var-less variables in TypeScript class definitions?

Why is it that when creating a component class in Angular2, we don't need to use var when declaring a new variable? For example: @Component({ selector: 'my-app', template: ` <h1>{{title}}</h1> ` }) export class AppCo ...

A guide on selecting the best UI container based on API data in React using TypeScript

I have been developing a control panel that showcases various videos and posts sourced from an API. One div displays video posts with thumbnails and text, while another shows text-based posts. Below is the code for both: <div className=""> &l ...

Issue in TypeScript: The module "*.svg" does not have a component that is exported named "ReactComponent"

I'm attempting to bring in an .svg file as a React component using TypeScript. As per the React documentation, the process should look like this: import { ReactComponent as Icon } from './Icon.svg'; Referring to the TypeScript documentati ...