Typescript implementation of abstract class with dynamic return types

I have a unique abstract class named 'AbstractDetailsService' defined as follows:

import { Injectable } from '@angular/core';

export class DetailEntities<T> {
 id: number;
 role:  string;
 data: T[];
}

export class User {
 name: string;
 age: number;
}

export class Customer {
 customerName: string;
 customerAge: number;
}

@Injectable()
export abstract class AbstractDetailsService<T> {
 abstract get(entity: string): DetailEntities<T>;
}

Next, there is a class called 'PersonDetailsService' which implements the above class and can return either a User or a Customer based on the entity passed.

import { Injectable } from '@angular/core';
import { AbstractDetailsService, Customer, DetailEntities, User } from './abstract-detail.service';

@Injectable()
export class PersonDetailsService implements AbstractDetailsService<DetailEntities<any>> {

get(entity: string): DetailEntities<any> {
   if (entity === 'user') {
     const users: User[] = [{name: 'abc', age: 21}]
     const userDetails: DetailEntities<User> = {id: 1, role: 'Developer', data: users};
     return userDetails;
   }
   const customers: Customer[] = [{customerName: 'abc', customerAge: 21}]
   const customerDetails: DetailEntities<Customer> = {id: 1, role: 'Developer', data: customers};
   return customerDetails;
 }
}

Presented below is my component code where I inject PersonDetailsService into the providers array:

import { Component, OnInit, VERSION } from "@angular/core";
import {
 AbstractDetailsService,
 DetailEntities,
User
} from "./abstract-detail.service";
import { PersonDetailsService } from "./person-detail.service";

@Component({
 selector: "my-app",
 templateUrl: "./app.component.html",
 styleUrls: ["./app.component.css"],
 providers: [
   {
     provide: AbstractDetailsService,
     useClass: PersonDetailsService
   }
 ]
})
export class AppComponent implements OnInit {
 name = "Angular " + VERSION.major;
 details: DetailEntities<User>;

 constructor(private readonly detailService: AbstractDetailsService<any>) {}

 ngOnInit(): void {
   const entity = "user";
   this.details = this.detailService.get(entity);
 }
}

I am seeking guidance on how to replace the generic type any with either User or Customer. How can I customize the 'get' function to dynamically determine its return type? Additionally, I want to restrict the generic type to only accept User and Customer types.

For further exploration, visit this Stackblitz URL - https://stackblitz.com/edit/angular-typescript-dynamic-return-type?file=src%2Fapp%2Fperson-detail.service.ts

Your assistance on this matter would be greatly appreciated :-)

Answer №1

One possible solution might involve utilizing the concept of a union type.

Rather than

get(entity: string): DetailEntities<any>

You could instead define

get(entity: string): DetailEntities<User | Customer>

An alternative, more intricate approach could incorporate the use of conditional types.

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 best way to navigate a link in Angular (15) that requires multiple parameters to be input?

I came across the following link: "https://api.api-soccer.com/v1/championship/10/stages/168" My goal is to access the data within the ID /168, but I first need to access the ID at /10. Unfortunately, I'm unsure of how to achieve this using Angular. ...

Performing bulk operations on all selected rows in a table using Angular 6

Within my Angular 6 web application, there is a table with checkboxes in each row. My goal is to be able to perform bulk actions on the selected rows, such as deleting them. One approach I considered was adding an isSelected boolean property to the data m ...

What steps should be taken if a typings (or tsd) file cannot be found?

After reading through the TypeScript handbook, I realized that I couldn't find the solution to my problem. What are my options if I'm using a library without existing typings? The first option is to create the typings file myself, but I'm ...

Elucidate a crucial aspect within a broad context

It seemed like I had a good grasp on how to tackle this, but clearly there's a misstep somewhere. I'm aiming to create a function that acts as a typeguard; its main purpose is to ascertain whether an input is an object containing a specified key ...

Arrange in chronological order and organize based on an external array

Presenting an Array of Objects with various transactions: [{ date: 2022-04-07T01:00:00.000+00:00, type: 'profit' amount: 200 },{ date: 2022-04-07T01:00:00.000+00:00, type: 'withdraw' amount: 600 },{ date: 2022-04-07T01:00: ...

Discover which references are yet to be resolved within a tsx file

I have been tasked with developing a custom builder for a web application. The challenge now is to automatically detect imports in the code so that the right modules can be imported. My current solution involves traversing the AST of the scripts, keeping ...

Troubleshooting problems with connecting two Angular projects using Npm

For a while now, I've been facing a challenge when working on an Angular project that utilizes npm link with a library that has its own node modules folder. Each project needs its own set of node modules because they both have their own components and ...

Troubleshooting issues with setTimeout in Angular 2 using typescript

Within this HTML code, I am monitoring the page for idle activity. If the user is idle for a certain period of time, an inactivity alert will be displayed and the user will be logged out. <div *ngIf="environmentData" xmlns="http://java.sun.com/jsf/html ...

A step-by-step guide on combining multiple projects into one using iframes

Within our organization, we have three separate Angular projects. A client has requested that we develop a new project allowing users to access each of these individual projects. My inquiry pertains to whether using iframes is the appropriate technology ...

The argument '$0' provided for the pipe 'CurrencyPipe' is not valid

When retrieving data from the backend, I receive $0, but I need to display it as $0.00 in my user interface. <span [innerHTML]="session.balance | currency :'USD': true:'1.2-2'"></span> I'm encountering an issue where ...

What is the best way to randomize the order of input form elements in Angular 4

I have a project in progress where I am developing an application featuring a form with dynamic input elements. By "dynamic," I mean that these inputs will be generated from server-side data. Here is a simplified example of what the HTML structure could lo ...

Learning how to use arrow functions with the `subscribe` function in

Can someone help clarify the use of arrow functions in TypeScript with an example from Angular 2's Observable subscribe method? Here's my question: I have code that is functional: this.readdataservice.getPost().subscribe( posts =&g ...

Transition from tslint to a new linter

Is it possible to remove tslint globally and switch to using eslint as the default in my Angular projects? When creating a new project with the command ng new myProj, I would like to have an eslint.json file instead of tslint.json. ...

Remove focus from input field after submitting in a project using Typescript and React with react-hook-form

I'm currently working on a TS-React project and encountering an issue with barcode scanning in my inputs. I am using react-hook-form along with the useForm Hook. The form consists of one input-text field and a submit button, both within a global form. ...

Is there a way to retrieve the request URL within the validate function of the http strategy?

Is it possible to access the context object present in guards within the validate method of my bearer strategy, by passing it as an argument along with the token? bearer-auth.guard.ts: @Injectable() export class BearerAuthGuard extends AuthGuard('be ...

Testing the value of an input in Angular using unit tests

Currently, I am delving into the official documentation of Angular2 which focuses on unit testing (https://angular.io/docs/ts/latest/guide/testing.html). My struggle lies in setting a component's input field value so that it reflects in the component ...

Simulated outcome of function call on a faked ES6 class

I've encountered a challenge with mocking a method while mocking an ES6 class using the MockedClass feature of the jest library. For instance: export default class CalculatorService { constructor() { // setup stuff } public add(num1: numbe ...

What is the process to retrieve Azure Static Web Apps Application Settings within an Angular application?

After deploying my Angular App as a Static Web App in Azure, I am exploring the use of Application Settings in Configuration to dynamically change variables in my environment.ts file. This way, I can easily switch between different APIs and Application Ins ...

Exploring how to iterate through an object to locate a specific value with TypeScript and React

I am looking to hide a button if there is at least one order with status 'ACCEPTED' or 'DONE' in any area or subareas. How can I achieve hiding the "Hide me" menu item when there is at least one area with orders having status 'ACCE ...

When attempting to push a value in Angular 2 using TypeScript, the result may

I am encountering an issue where I can see 'sm' in the console.log result before trying to push it, however, it becomes undefined when I attempt to push. chooseMenu(menu:Menuitems){ const sm = {name:menu.name,quantity:1,price:menu.product[(&apos ...