Extending a class with diverse types in Typescript: A guide

I have a class with multiple methods that deal with an entity referred to as "entity."

class entity {
  entityName: string = '';

  getList(): any[] {
    someAPI + this.entityName ....
  }

  getOne(): any{
  }
}

Additionally, there are specific entities that extend from the base class:

class person extends entity {
entityName: string = 'person';
}

class order extends entity {
entityName: string = 'order';
}

I would like to specify the entity type for each new class. Instead of inheriting the generic method getList(): any[] {}, I want to customize it for each subclass. For example, in the person class:

getList(): IPerson[] {
}

And for the order class:

getList(): IOrder[] {
}

Is there a way to set an interface type in each inherited class similar to how I am setting the entityName?

Answer №1

Discover Generic classes here.

Implement a generic type on your entity class (can be abstract) and specify it when extending (extends Entity<IOrder>).

Sample code:

/* === Entity === */
interface EntityOptions {
    name: string;
    anotherOption?: any;
    anotherOptionWhyNot?: any;
}
abstract class Entity<T> {
    protected readonly entityOptions: EntityOptions;

    public constructor(entityOptions: EntityOptions) {
        this.entityOptions = entityOptions;
    }

    public getOne(): T {
        // Call to API ...
        console.info(`Calling API (one) ${this.entityOptions.name} ...`);

        // DO NOT COPY THIS!
        return {} as T;
    }

    public getList(): T[] {
        // Call to API ...
        console.info(`Calling API (list) ${this.entityOptions.name} ...`);

        // DO NOT COPY THIS!
        return [] as T[];
    }
}

/* === Person === */
interface IPerson {
    id: number;
    name: string;
}
class Person extends Entity<IPerson> {
    public constructor() {
        super({ name: 'person' });
    }
}

/* === Order === */
interface IOrder {
    id: number;
    date: Date;
}
class Order extends Entity<IOrder> {
    public constructor() {
        super({ name: 'order' });
    }
}

/* ---------------- */
// ERROR: Cannot create an instance of an abstract class.(2511)
// const entity = new Entity({ name: 'ItDoesNotWork' });

// Person
const person = new Person();
console.log(person.getOne());
console.log(person.getList());

// Order
const order = new Order();
console.log(order.getOne());
console.log(order.getList());

PS: This is also available on the Typescript Playground here.

Answer №2

An easy and straightforward method for returning self in extended classes looks like this

class Entity {
  entityName: string = '';

  getList(): this[] {
    return [];
  }

  getOne(): this {
    return this;
  }
}

class Person extends Entity {}

new Person().getOne(); // returns 'this'
new Person().getList(); // returns 'Person[]'

If this approach isn't sufficient, you may need to utilize generics or "reimplement" the necessary functions.

getOne(): anyTypeYouWant {
  super().getOne()
}

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

The data remains undefined even after being initialized in the constructor

My goal is to extract queryParams from a URL and leverage that information to resolve data in the following manner: data = { searchValue: null || undefined }; constructor(private http: HttpClient, private route: ActivatedRoute) { route.queryParams.su ...

I find that the value is consistently undefined whenever I attempt to set it within a promise in Angular

Hi there, I've encountered an issue with my getData() function in accountService.ts. I'm attempting to fetch user data and user account data simultaneously using a zip promise. Although the resolve works correctly and I receive the accurate data, ...

Having trouble retrieving values from Promise.allSettled on Node.js 12 using TypeScript version 3.8.3

Currently, I am delving into NodeJs 12 and exploring the Promise.allSettled() function along with its application. The code snippet that I have crafted allows me to display the status in the console, but there seems to be a hitch when attempting to print t ...

Modify the value of mat-slide-toggle from TypeScript code

This is the HTML code I have for a mat-slide-toggle element, with a toggleStatus() function: <span class="form-control form-control-plaintext"> <mat-slide-toggle name="status" checked="" ...

The function within filereader.onload is not running properly in JavaScript

When working with FileReader to read a file and convert it to base64 for further actions, I encountered an issue. Although I was able to successfully read the file and obtain its base64 representation, I faced difficulties in utilizing this data to trigger ...

How to retrieve the value of a variable accessible to all users in Angular?

In my code, I am working with a service variable called Users. Service: Users:BehaviorSubject<Array<any>> = new BehaviorSubject([]); I am updating the values in the component using this code: this.Service.Users.next([...this.Service.User ...

Creating Algorithms for Generic Interfaces in TypeScript to Make them Compatible with Derived Generic Classes

Consider the (simplified) code: interface GenericInterface<T> { value: T } function genericIdentity<T>(instance : GenericInterface<T>) : GenericInterface<T> { return instance; } class GenericImplementingClass<T> implemen ...

Custom Typescript type that runs concurrently with the base type is disregarded

Assumption: When creating a custom type that mirrors an existing type, the expectation is for variables assigned to that type to maintain it and not default back to the base type. In the function f provided below, the expected return type should be Dog ins ...

Issues with implementing AddEventListener in InAppBrowser on IONIC 2

I am currently working on implementing AddeventListener to listen for 'Exit' and 'LoadStart' events in InAppBrowser within IONIC2. Here is my HTML: <button (click)="browsersystem('https://www.google.com')" > Visit URL& ...

Exploring the process of extending Shoelace web components with Typescript using Lit

Once I extended the <sl-button> component in Lit, I realized that TypeScript was not catching errors for incorrect attributes being passed. For instance, in the code snippet provided below, when I use <sl-button> with an incorrect attribute, ...

Having trouble accessing @ViewChildren from the parent component

I've been facing an issue while attempting to control the child instances of a component and I can't seem to bypass this particular error. I've been referring to solutions provided on this specific thread. The main component Sequence houses ...

What are the best practices for handling dynamic content internationalization in Angular?

According to Angular.io, the i18n tag is used to mark translatable content. It should be placed on every element tag that requires translation of fixed text. Now, what if we have an element with dynamic content? For example, consider a table displaying a ...

What is the best way to initiate the registration page through the @auth0/auth0-react library?

I've hit a roadblock in trying to automatically launch the sign-up (registration) page using @auth0/auth0-react. Previously, I would send mode which worked with auth0-js. So far, I have attempted the following without success: const { loginWithRedir ...

Tips for utilizing innerHTML in TypeScript code within an Angular 2 application

Is there a way to utilize innerHTML from TypeScript code in Angular 2 RC4? I'm facing an issue: I need to dynamically add precompiled HTML code when a specific button is clicked. For instance: TypeScript code private addHTML() { // not sure how ...

Is it possible to define TypeScript interfaces in a separate file and utilize them without the need for importing?

Currently, I find myself either declaring interfaces directly where I use them or importing them like import {ISomeInterface} from './somePlace'. Is there a way to centralize interface declarations in files like something.interface.ts and use the ...

Specify the return type based on specific parameter value

I'm facing a situation where I have two definitions that are identical, but I need them to behave differently based on the value of the limit parameter. Specifically, I want the first definition to return Promise<Cursor<T>> when limit is g ...

What is the proper way to implement jest.mock in a describe or it block?

Using typescript and jest, I am faced with a scenario involving two files: users.service.ts, which imports producer.ts. In an attempt to mock a function in producer.ts, I successfully implement it. import { sendUserData } from "./users.service"; const pro ...

Dropdown box not displaying any choices

I developed a basic reusable component in the following way: Typescript (TS) import {Component, Input, OnInit} from '@angular/core'; import {FormControl} from '@angular/forms'; @Component({ selector: 'app-select', templa ...

The 'filter' attribute is not found in the 'ContextProps' type

I am currently working on a project in Next.js 13 where I am trying to render card items conditionally based on their status. The TypeScript version being used is "5.2.2". However, I encountered an error that says: Property 'filter' does not exis ...

Transferring data to a different module

I'm currently working on an Angular program where I am taking a user's input of a zip code and sending it to a function that then calls an API to convert it into latitude and longitude coordinates. Here is a snippet of the code: home.component.h ...