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

Encountering issues with Typescript when providing parameters for res.status().json()

I've recently started using Typescript and I'm still in the learning process by converting some existing JS code to TS. In my code: res.status(200).json({ user: data.user }) I encountered a red squiggly underline under user:data.user ...

Using function overloading in TypeScript causes an error

I'm currently exploring the concept of function overloading in TypeScript and how it functions. type CreateElement = { (tag: 'a'): HTMLAnchorElement (tag: 'canvas'): HTMLCanvasElement (tag: 'table'): HTMLTableElem ...

When clicking initially, the default input value in an Angular 2 form does not get set

I am currently learning angular2 as a beginner programmer. My goal is to create a form where, upon clicking on an employee, an editable form will appear with the employee's current data. However, I have encountered an issue where clicking on a user f ...

Transform the date format from Google Forms to TypeScript

I am currently facing an issue with a Google Form connected to a Google Spreadsheet. The date format in the spreadsheet appears as follows when a response is received: 20/02/2023 18:58:59 I am seeking guidance on how to convert this date format using Type ...

Issue with rendering React Toastify

I'm running into an issue while trying to integrate react toastify into my react vite application. Specifically, I keep getting an error related to useSyncExternalStore even after attempting to switch to version 9 of react toastify. My React version i ...

How can I display 4 react components, such as custom buttons, in a manner that ensures the most recently pressed button appears on top?

I've been attempting to solve this problem, but I'm struggling to find a solution. My current approach involves grouping the 4 button components in an array and shifting their positions based on user input. Is there a more efficient way to accomp ...

Is there a specific type of function missing in Typescript?

I am facing a challenge in converting an existing JavaScript code to Typescript. The original javascript code is as follows: object.getsomething( function(err, result) { // async }); I am confused about how to properly type the parameter "function(er ...

Tips for creating a dynamic interface in TypeScript to eliminate repetitive code

Currently, I am utilizing typescript alongside the react-navigation library within my react-native project. Following the guidelines provided in the official documentation, I have been annotating my screens. One issue I have encountered is the repetitive ...

What is the best way to execute 2 statements concurrently in Angular 7?

My goal is to add a key rating inside the listing object. However, I am facing an issue where the rating key is not displaying on the console. I suspect that it might be due to the asynchronous nature of the call. Can someone help me identify what mistak ...

Comparison between a Typescript optional field and a field that has the potential to be undefined

Can you clarify the contrast between an optional field and a T | undefined field? export interface Example { property1: string | undefined property2?: string } ...

Why does TypeScript not recognize deconstructed arrays as potentially undefined variables?

When looking at the code snippet below, I was under the impression that the destructured array variables, firstName and lastName, would be classified as string | undefined. This is because the array being destructured could have fewer variables compared ...

Tips for creating type-safe assertion functions in TypeScript

In TypeScript 3.7, a new feature allows the writing of "assertion functions." One example is shown below: export type TOfferAttrName = keyof typeof offerAttrMap; export const assertIsOfferAttrName = (name: string): asserts name is TOfferAttrName => { ...

Creating a unique Nest.js custom decorator to extract parameters directly from the request object

I am working with a custom decorator called Param, where I have a console.log that runs once. How can I modify it to return a fresh value of id on each request similar to what is done in nestjs? @Get('/:id') async findUser ( @Param() id: stri ...

Troubleshooting: Difficulty with Angular 2 TypeScript interface array functionality

Currently, I am developing an Angular 2 application where I aim to showcase messages by utilizing an interface and storing all the messages in an array. Below is a snippet of my TypeScript component that highlights this functionality: export class ChatCom ...

Encountering a duplication issue when redirecting components in Angular2/TypeScript using navigateByUrl

Seeking guidance on implementing the login function where the current component redirects to another one upon clicking the login button. Below are my .ts and .html files: login.component.ts login.component.html The issue arises when using npm start for ...

What could be the reason for the Angular dropdown values not appearing?

Encountering an issue with binding data to a dropdown element, as the dropdown displays NOTHING SELECTED. <select #classProductTypeCombobox name="classProductTypeCombobox" class="form-control col-md-3" [(ngModel)]="classifica ...

Encountering a problem with the 'string' parameter when using TypeScript

I keep encountering the following error message: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ barkingRoadProject: string[]; }'. No index signature with a paramet ...

The argument provided is a string type, which cannot be assigned to a parameter expecting an object with a 'results' property of type string

When attempting to pass the result.nativeEvent.message to another function, I am encountering the error: Argument of type 'string' is not assignable to parameter of type '{ results: string; } on onUnityMessageController(result.nativeEvent.me ...

Creating numerous bar graphs for each specific date

I have a dataset containing dates and corresponding information for each element. Despite trying various approaches, I am unable to create a barchart. Every solution I've attempted has been unsuccessful thus far. The dataset is structured as follows ...

The type 'EventTarget & HTMLTextAreaElement' does not contain the property 'files'

When trying to call a method in React TypeScript on the onChange Event of a MUI Input field, an error is encountered. The error message received is: Type '(event: { target: { files: any[]; }; }) => void' is not assignable to type 'Chang ...