Enhanced interface with plugins

I've been developing a "manager" class that allows for the integration of "plugins". Each plugin has the ability to enhance the data property of the manager class.

// manager.ts
interface Data {
    // some props
}

class Manager {
    data: Data;
    // TSC Problem: "Property 'data' has no initializer and is not definitely assigned in the constructor."

    constructor() {
        // It's not possible to set all potential properties of this.data because
        // the Manager class is unaware of all possible plugins that may be added
    }
}

Plugins receive a reference to the manager instance they are being plugged into. They can also enhance the Data interface to better define the data object?

// plugins/A.ts
interface Data {
    // additional props
}

function A(boss: Manager) {
    // "A" adds unique data to boss.data specific to "A"
}

These are the questions that come to mind:

  1. Is this a sound design pattern?
  2. Is this the best way to achieve this, or are there alternative solutions?

I came across information on Declaration Merging (https://www.typescriptlang.org/docs/handbook/declaration-merging.html), which seems like the most suitable option due to the number of independent plugins involved. Discriminated Unions (https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types) might not be feasible in this scenario.

EDIT: To clarify my query; Can declaration merging be used across multiple files?

Answer №1

The reason for the error message is due to not assigning a value to the data property when it is declared as type Data. To resolve this, you can initialize the value through the constructor:

interface Data {
  title: string;
}

class Employee {
  public data: Data;

  constructor(data: Data) {
    this.data = data;
  }
}

Then, you can create instances like this:

const worker: Employee = new Employee({ title: "worker" });

Answer №2

After some experimentation, I finally cracked the code.

// Manager.ts
interface Data {
    // potentially includes some properties
}

class Manager {
    data: Data;
    // Typescript Error: "Property 'data' has no initializer and is not definitely assigned in the constructor."

    constructor() {
        // Unable to assign all possible properties to this.data because the Manager class does not have prior knowledge
    }
}

// plugins/A.ts
declare module "../Manager" {
  interface Data {
    Scale: number;
  }
}

function A(boss: Manager) {
    // "A" appends unique data to boss.data that pertains specifically to "A"
}

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

How can I incorporate multiple quality sources into a flowplayer using Angular?

Is there a way to add multiple sources with different qualities like 1080p, 720p etc.? Thank you in advance. flowplayer('#my_player', { src: '../assets/videos/video_1080p.mp4', // title: 'This is just demo&apo ...

The CoreUI Sidebar gracefully hovers over the main page content

I recently started using CoreUI to design the layout for my application, but I ran into an issue while trying to integrate the Sidebar. Although the Sidebar is visible on the left side, I'm having trouble making sure that the router-view takes up the ...

Error in GoogleMapReact with Next.js: TypeError occurs when trying to read properties of undefined, specifically 'getChildren'

Currently, I am working on a basic nextjs application using the google-map-react component and nextjs. However, I keep encountering an error whenever I try to utilize the component. The error message reads as follows: "TypeError: can't access propert ...

The inRequestScope feature seems to be malfunctioning and is not functioning as intended

Need help with using inRequestScope in inversifyJS For example: container.bind<ITransactionManager>(Types.MysqlTransactionManager).to(MysqlTransactionManager).inRequestScope() ... container.get<ITransactionManager>(Types.MysqlTransactionMana ...

I am looking to generate an array with key-value pairs from an object that will be seen in the examination

I have a task that involves configuring a table and creating objects with key-value pairs for each key. type KeyValuePair<T> = {/** ... */}; let userKeyValuePair :KeyValuePair<{id:number,userName:string}>; // => {key:'id',value: ...

Oops! An unhandled promise error occurred when trying to fetch a URL with a status of 0. The response received has a status code of

I keep encountering an error whenever I try to hit a post request URL: Error: Uncaught (in promise): Response with status: 0 for URL: null at c (http://localhost:8100/build/polyfills.js:3:19752) at c (http://localhost:8100/build/polyfills.js:3:1 ...

Can you explain the distinction between these two TypeScript classes, one with a constructor and one without?

I am currently following Angular's official documentation called The Tour of Heroes and I have made slight modifications to it. As a result, there are now two distinct ways to define a class as shown below: user.ts export class User { url: string; ...

Remove user from authentication in Supabase in case of unsuccessful user creation in the database when signing up

My current setup involves using supabase authentication for user sign up. Upon successful sign up, I am inserting user details into a "profiles" table. However, I am concerned about the scenario where a user successfully signs up with supabase auth but f ...

In Angular, encountering difficulty accessing object members within an array when using custom pipes

Here is a custom pipe that I have created, but I am facing an issue accessing the members of the customfilter array, which is of type Item. import { Pipe, PipeTransform } from '@angular/core'; import {Bus} from '/home/pavan/Desktop/Pavan ...

Typescript error: Cannot assign type to argument

Exploring the world of typescript (2.5.2) and looking for clarity on why the first call works but the second one encounters an error: function printPerson(person: {firstName: string; lastName: string}): void{ console.log(person.firstName + " " + per ...

The malfunctioning collapse feature in Bootstrap 4 sidebar within an Angular 6 application

I am trying to find a way to collapse and reopen the sidebar when clicking on a button. I have attempted to create a function to achieve this, but unfortunately it did not work as expected. Important: I need to collapse the sidebar without relying on jque ...

Instructions on utilizing type interfaces for prop drilling in my React Typescript counter

I am currently developing a basic counter app to monitor my progress in a digital card game that I enjoy playing. While attempting to pass props from the parent component to the child component, I encountered an issue where the props were not being success ...

Seamless Navigation with Bootstrap Navbar and SmoothScroll

Currently, I have a custom-built navbar that functions perfectly, with full mobile responsiveness. However, I am facing an issue with the nav-item's (headings). The nav-item's direct users to different sections of the same page using #. I have i ...

Troubleshooting Typescript Compilation Error in React - Cannot assign type 'Element' to type 'FunctionComponent<{}>'

The code snippet originally utilized - import { Create } from '@material-ui/icons'; <DroppableFolder count={draftsCount} sidebarOpen={open} folderId={FolderType.Drafts} Icon={Create} name="Dr ...

I can't figure out why I'm receiving undefined even though all the variables are populated with the necessary

I have been working on a project that involves implementing email and password authentication using Firebase. However, I encountered an error when the user submits their credentials: FirebaseError: Firebase: Error (auth/admin-restricted-operation). at ...

encountered an issue when testing a dynamic route in Next.js with postman

I recently created a new API route named route.ts, where I included two different routes. One route retrieves all users from the database, while the other retrieves a specific user based on their ID passed as a query parameter. However, when testing these ...

Data from HTML not being transferred by Angular Forms

I am facing an issue with transferring input data from HTML's <select> element to Angular Forms. Let's take a look at my code first. File Name: home-page.component.html <form [formGroup]="rForm" (ngSubmit)="addPaste(rForm.value)"> ...

What is the best way to display loading details during a data loading process within a useEffect hook?

Whenever a specific custom React component I've created is initially mounted, it utilizes useEffect to initiate a lengthy multistep process of loading data that will later be rendered. Since the component isn't always rendered, this costly proces ...

Is it possible to compile using Angular sources while in Ivy's partial compilation mode?

Error: NG3001 Unsupported private class ObjectsComponent. The class is visible to consumers via MasterLibraryLibModule -> ObjectsComponent, but is not exported from the top-level library entrypoint. 11 export class ObjectsComponent implements OnInit { ...

Tips for formatting a Date field within an Angular application

After receiving a stringVariable from the backend service, I successfully converted it into a Date field with the following code snippet. date d = new Date(stringVariable ); While this conversion worked fine, the resulting date format is not what I requ ...