Implement new interface methods on-the-fly

I am seeking a way to dynamically incorporate methods that are defined in an interface. Initially, I considered using the index signature approach, but unfortunately, not all methods have the same signature. My objective is to preserve all type information.

The current basic code does not compile because not all methods are implemented. When I introduce Partial, it compiles successfully, but it seems like I lose the type information.

import anotherLib from "anotherLib";

interface IALotOfMethods<T> {
  methodA(): T;
  methodB(opts: MyOpts): T;
  ...
}

interface IMyClass<T> extends IALotOfMethods<T> {
  getName(): string;
  getSomething(): number;
}

class MyClass implements IMyClass<MyClass> {
  results: any[] = [];

  getName(): string {
    return "A Name";
  }

  getSomething(): number {
    return 0;
  }
}

const aLotOfMethodsList = ['methodA', 'methodB', ...];

aLotOfMethodsList.forEach(funcName => {
  MyClass.prototype[funcName] = function(opts: any) {
    this.results.push(anotherLib[funcName](opts));
    return this;
  }
})

const myObj = new MyClass();
myObj.methodA(); // methodA should be available/autosuggested

Is there a way to achieve this? Do I have to manually implement all methods even though they have similar structures? Will I need to sacrifice type information?

Thank you.

Answer №1

If you're looking for a solution that has been implemented before, one approach can be seen in the code snippet below where class and interface merging is utilized along with optional properties:

interface Component {
   optionalMethod?(l: GetLocalization): void;
}
abstract class Component {
    public abstract mustImplement(): void;
}

class Post extends Component {
    public mustImplement(): void {}
}

You can see this in action on Stackblitz.

While the auto complete feature works, it's important to note that there may be a "can't call an undefined method" warning, so caution is advised.

For those looking for an even more streamlined solution without double merging:

import anotherLib from "anotherLib";

abstract class Component<T> {
    methodA?(): T;
    methodB?(opts: string): T;
    public abstract mustImplement(): void;
}

class Post extends Component<string> {
    public mustImplement(): void {
  }
}

const aLotOfMethodsList = ['methodA', 'methodB'];

aLotOfMethodsList.forEach(funcName => {
  (Post as any).prototype[funcName] = function(opts: any) {
    this.results.push(anotherLib[funcName](opts));
    return this;
  }
})

const myObj = new Post();
myObj.methodA(); // autocomplete

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

What is the process for including a new attribute to the Component in the _app.tsx file when using Next.js along with Typescript?

Currently, I am in the process of developing some secure pages using Next.js, NextAuth.js, and Typescript. While referencing code from my _app.tsx, which was sourced from the official NextAuth.js website, I encountered an issue where a property named auth ...

Tips for displaying dynamic images using the combination of the base URL and file name in an *ngFor loop

I have a base URL which is http://www.example.com, and the file names are coming from an API stored in the dataSource array as shown below: [ { "bid": "2", "bnam": "ChickenChilli", "adds": "nsnnsnw, nnsnsnsn", "pdap": " ...

Which property within the <mat-option> element is used for toggling checkboxes on and off?

I'm experimenting with dynamically checking/unchecking a checkbox in mat-option. What attribute can I use for this? I've successfully done the same thing with mat-checkbox using [(ngModel)]. Here's the snippet of my code: app.component.html ...

The application within the Main Module is not being acknowledged by the other components within the module

I am facing an issue with my AngularJS application where the directive I created within the 'FormTest' module is not recognizing the variable 'app' even though it is defined within the same module. The error message I receive is TS2304 ...

The risk of a race condition could arise when working with nested switchMaps in ngr

I am currently working on an Angular 9 application that heavily relies on observables. In a specific component, I have the following requirements: Retrieve all companies to access certain information. Fetch all responses and link additional company detai ...

class-validator: ensures the correct number of digits are present in numeric values

Seeking assistance on validating the number of digits for numeric values using class-validator. Specifically, I want my entity to only accept numbers with 6 digits for a certain property. For example: const user1 = new User(); user1.code = 123456 // should ...

Are you ready to put Jest to the test by checking the completion event of

The RxJS library's Observer triggers three main events: complete error next If we want to verify the occurrence of the complete event using Jest, how can this be achieved? For instance, we are able to test the next and error events by checking for ...

The variable is currently undefined because it has an array assigned to it

Upon selecting multiple checkboxes for variants, I am retrieving checked data using the following method: get selectedIdsFromViolCategoriesFormArray(): string[] { return this.violCategories .filter((cat, catIdx) => this.violCategoriesFormArr. ...

Should Errors be Handled in the Service Layer or the Controller in the MVC Model?

Currently, I am in the process of developing a Backend using Express and following the MVC Model. However, I am uncertain about where to handle errors effectively. I have integrated express-async-errors and http-errors, allowing me to throw Errors anywher ...

Exploring the world of Typescript and Angular Filter functionalities

I am looking to utilize one of my Angular Filters in my controller as a function. I came across a solution on this page: How to use a filter in a controler The last answer provided exactly what I needed, so I implemented it in my JS code: var MyFunc ...

Angular 2 ngFor generates a collection of rows and columns forming a single large column

It seems that ngfor is generating divs one by one, resulting in a poor design where they are stacked on top of each other. I would like to achieve a layout like this: [1] [2] [3] [4] [5] [6] However, the current outcome looks like this: [ 1 ] [ 2 ] [ 3 ...

Obtaining the interface for a Typegoose class model

I am currently exploring how to create an abstraction for Mongo model functions and looking into ways to reuse the model interface from a typegoose class. My goal is to have a function like this: import CountryModel, { Country } from '../../models/ ...

Is there a way to ensure an ajax call finishes executing without relying on 'async: false' or callbacks?

In my view, I have implemented a TypeScript code defining a KnockoutJS binding handler for a clickable element as shown below: module MyModule { export interface ICopyButtonParams { dataUrl: string; } ko.bindingHandlers.copyButton = { ...

Encountering difficulty when trying to define the onComplete function in Conf.ts. A type error is occurring, stating that '(passed: any) => void' is not compatible with type '() => void'.ts(2322)'

I have been developing a custom Protractor - browserstack framework from the ground up. While implementing the onComplete function as outlined on the official site in conf.ts - // Code snippet to update test status on BrowserStack based on test assertion ...

In TypeScript, values other than numbers or strings can be accepted as parameters, even when the expected type is a

The issue I am encountering with TypeScript is quite perplexing, especially since I am new to this language and framework. Coming from a Java background, I have never faced such a problem before and it's presenting challenges in my bug-fixing efforts ...

Angular 2 forms are displaying ngvalid when input fields are marked as nginvalid

The form displays ngvalid because I have included the code like this: <form novalidate class="pop-form" (submit)="signUp()" #regForm="ngForm"> <div class="group"> <input type="text" [(ngModel)]="signUpData.name" [ngMode ...

Trouble with Excel Office Script setInterval functionality

Trying to automatically recalculate an Excel worksheet every second using Office Script. Unfortunately, my initial approach did not succeed. function sendUpdate(sheet: ExcelScript.Worksheet) { console.log('hi'); sheet.calculate(true); } func ...

Converting API response into a class instance using `class-transformer` in TypeScript: A step-by-step guide

When working with TypeScript, I have a regular method called Request(method: HttpMethod, url: string, ...) that is used for calling APIs. Now, my goal is to convert the response from this API request into an instance of a class using class-transformer (or ...

gRPC error: "unable to connect to the specified address" while running a NestJS application on Docker

I am encountering this particular error message when trying to run my NestJS application in a Docker container with gRPC: { "created": "@1616799250.993753300", "description": "Only 1 addresses added ou ...

The RxJS observable fails to initiate the subscribe function following the mergeMap operation

I am attempting to organize my dataset in my Angular application using the RxJS operators and split it into multiple streams. However, I am facing difficulties making this work properly. Inside my SignalRService, I have set up a SignalR trigger in the cons ...