Utilizing typescript to isolate specific functionality from a class without extending it

Imagine a scenario where I have a class with different areas of functionality:

export class TreeTable extends someOtherClass {
    constructor(){
       super.constructor();
    }
   //========= area 1 of functionality ====
   itemRightClick(){this.contextMenu();}
   contextMenu(){
     // open file or folder context menu
   }
   fileContextMenu(){}
   folderContextMenu(){}

   //========= area 2 of functionality ====
   loadData(){}
   subScribeStuff(){}
   unsusbscribeStuff(){}

   //======== area 3 SomeOtherClasses functionality
   someOtherClassMethod_1(){
   this.someOtherClassMethod();
   super.someOtherClassMethodTwo();
  }
}

If I decide to separate and extract abstract area-1 into an external class.

class ContextMenu {
   constructor(){}
    //========= area 1 of functionality ====
   itemRightClick(){this.contextMenu();}
   contextMenu(){
     // open file or folder context menu
   }
   fileContextMenu(){}
   folderContextMenu(){}
}
export class TreeTable extends someOtherClass {

    constructor(){
       super.constructor();
    }
   //======== AREA 1
   // DECORATE THIS CLASS WITH class ContextMenu AND ADD ITS METHODS
   //========= area 2 of functionality ====
   loadData(){}
   subScribeStuff(){}
   unsusbscribeStuff(){}

   //======== area 3 SomeOtherClasses functionality
   someOtherClassMethod_1(){
   this.someOtherClassMethod();
   super.someOtherClassMethodTwo();
  }
}

It appears to be a straightforward task that can be achieved without using inheritance, but rather through decoration. It seems that decorators (@) are not suitable for this purpose.

Answer №1

One thing to keep in mind is that JavaScript, unlike traditional OOP languages, does not support abstract classes.

With your current class hierarchy, it can be challenging to selectively choose members from one class and transfer them to another without extending the entire class X.

To align with OOP and SOLID principles, you may need to reconsider how you model your objects. Your class seems to have multiple responsibilities such as data loading, subscribing/unsubscribing, and context menu operations. These functionalities could be separated into their own class definitions or abstracted through TypeScript interfaces.

When focusing on different areas of functionality (1-3), here are some options:

1. Separate each area of functionality into individual classes:

class Area1 {
  ...
}

class Area2 {
  ...
}

class Area3 {
  ...
}

You can then incorporate instances of Area1, Area2, or Area3 within TreeTable or create a type hierarchy.

2. Utilize TypeScript interfaces for defining class members:

interface IArea1 {
  ...
}

interface IArea2 {
  ...
}

interface IArea3 {
  ...
}

You can implement multiple interfaces to structure your concrete types accordingly:

class TreeTable extends someOtherClass implements IArea1, IArea3 {
  // implement members for IArea1
  // implement members for IArea2
}

3. Consider using regular JavaScript objects instead of OOP:

const area1 = {
  // functions
}

const area2 = {
  // other functions
}

const area3 = {
  // additional functions
}

const treeTable = {
  ...area1,
  ...area3
}

Even when using regular objects, abstract interfaces can still be beneficial:

interface ITreeTable extends IArea1, IArea3 {
  // specific functionality
}

const treeTable: ITreeTable = {
  // interface members
};

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

Heroku error: unable to locate tsc despite exhaustive troubleshooting efforts

I've been attempting to deploy a basic nodejs app on heroku, but I keep encountering the error mentioned above. Despite trying various solutions provided here, nothing seems to resolve the issue. Here's a summary of what I've attempted so fa ...

The intended 'this' keyword is unfortunately replaced by an incorrect '

Whenever the this keywords are used inside the onScroll function, they seem to represent the wrong context. Inside the function, it refers to the window, which is understandable. I was attempting to use the => arrow notation to maintain the correct refe ...

'Unable to locate the identifier "system" in Angular 2' - troubleshoot this unique error

My routes file contains a reference to 'system' which is causing an error in my Visual Studio Code. The error states that it cannot find the name 'system'. I have attached a screenshot for reference: https://i.sstatic.net/W2oD2.png ...

Unable to bring in a TypeScript library that was downloaded from a GitHub fork repository

Currently, I am working on developing a GitHub app using the probot library. However, I have encountered an obstacle as outlined in this particular issue. It seems that probot does not offer support for ESM modules, which are crucial for my app to function ...

A guide to resolving the error "Cannot read properties of undefined (reading 'length')" while implementing pagination with react, Material-UI, and TypeScript

As I work on my code, my goal is to display a limited number of cards per page based on the data stored in a JSON file. I anticipated that clicking on the ">" or "<" icon would navigate to the next or previous page respectively, updating the displaye ...

Transfer the unique field name to a universal assistant

Consider the code snippet provided in this playground: class A { private z = 0 } type K = "z" type ValidKeys = A[K] extends any ? K : never The type ValidKeys compiles correctly and matches K only when K represents a subset of keys from A. It ...

Exploring the mechanics behind optional chaining, known as the Elvis operator, in TypeScript. How does this feature operate within the

Can someone explain the concept of optional chaining (Elvis operator) in TypeScript and how it can be used effectively? public static getName(user: IUser){ if(user.firstName != null && user.firstName != ""){ return user.firstName; } ...

Creating a singleton in TypeScriptWould you like to know how to declare a singleton in

My goal is to incorporate an already existing library into my TypeScript project. The library contains a singleton object that I want to declare and utilize. For example, within the xyz.js file, the following object is defined: var mxUtils = { /* som ...

Ensure that selecting one checkbox does not automatically select the entire group of checkboxes

Here is the code I'm using to populate a list of checkboxes. <label class="checkbox-inline" ng-repeat="item in vm.ItemList track by item.id"> <input type="checkbox" name="item_{{item.id}}" ng-value="{{item.id}}" ng-model="vm.selectedItem" /& ...

What is the process for obtaining the complete URL using the getDownloadURL() function along with a token?

An error occurred due to an unresolved FirebaseStorageError: "storage/object-not-found". The message indicates that the object 'k91a73uzb99' does not exist in Firebase Storage. This type of error is categorized under FirebaseError with a code of ...

Utilizing next-redux-wrapper within the getServerSideProps function in Next.js allows for seamless

When trying to call an action function in getServerSideProps using TypeScript, I encountered some challenges. In JavaScript, it is straightforward: import { wrapper } from "Redux/store"; import { getVideo } from "Redux/Actions/videoAction&qu ...

Can a type name be converted into a string representation for use as a template literal type?

Is there a way to retrieve the string representation of a type name in order to return a more concise compile error message from a type function? I came across this solution (unfortunately, the article does not have anchor links so you will need to search ...

What makes FC function components stand out from traditional vanilla React function components?

I recently came across this FC function component: const LabelForm: FC<LabelFormProps> = ({ labels, selectedID, }) => { const selectedLabel = selectedID !== undefined && labels[selectedID]; In my usual implementation, I do it like t ...

Is there a way to denote a specific part of a generic type without explicitly specifying the parts as generics themselves?

My dilemma involves an object defined by a type from a 3rd party library: // Unable to modify this - it belongs to the 3rd party library; interface TypedEvent< TArgsArray extends Array<any> = any, TArgsObject = any > extends Event { args ...

The Console.log function first displays an Object, and then changes to display an Array containing a single object when clicked

When I utilize MobX to call an observable within my React component, something peculiar happens. Upon console logging the observable, initially it appears as an Object. However, upon clicking on it, the object transforms into an Array for that one particul ...

Is it feasible to alter the file name while utilizing express-fileUpload library?

Is there a way to modify the file name of an uploaded file on the server side? app.post(URL, (req, res) => { let fileName = req.files.file.name; req.fileUpload; res.statusCode = HTTP_OK; res.send("Good Job") }) The settings I have in uploadF ...

Ionic Framework: Implementing a search bar in the navigation bar

I am looking to include a search icon in the navbar of my Ionic project <ion-navbar> <ion-buttons left> <button ion-button menuToggle> <ion-icon name="menu"></icon-icon> </button> </ion-bu ...

Utilizing useClass in Angular's APP_INITIALIZER

Before my application starts up, I require some API data and am currently handling it with APP_INITIALIZER and useFactory. However, I aim to enhance the structure by separating all the code from app.module.ts: app.module.ts import { NgModule} from '@ ...

What steps do I need to take to ensure my TypeScript module in npm can be easily used in a

I recently developed a module that captures keypressed input on a document to detect events from a physical barcode reader acting as a keyboard. You can find the source code here: https://github.com/tii-bruno/physical-barcode-reader-observer The npm mod ...

Issues with the functionality of Angular Firebase Authentication Service

I am currently working on setting up an authentication service in Angular that will integrate with Google Firebase for a Login form. However, I have encountered an issue where including the service in the constructor of my LoginComponent prevents me from a ...