Preventing me from instantiating objects

I've been struggling with an issue for a while now

consider the following:

export abstract class abstractClass {
    abstract thing(): string
}

export class c1 extends abstractClass {
    thing(): string {
        return "hello"
    }
}

export class c2 extends abstractClass {
    thing(): string {
        return "world"
    }
}

export interface simpleInter {
    el: typeof abstractClass
}

const cls: simpleInter[] = [];
cls.push({
    el: c1
},{
    el: c2
})

for (const classObj of cls) {
    const c = new (classObj.el)() // error: Cannot create an instance of an abstract class. ts(2511)
    console.log(c.thing())
}

What baffles me is how can I instruct the compiler to recognize that I want classes which extend my abstractClass as the type.

Answer №1

To ensure proper implementation of your concrete classes, define a constructor function interface called CConstructor and use it as the base type instead of typeof abstractClass. By following this approach, you will be on the right track.

export interface CConstructor {
    new(): abstractClass
}

export abstract class abstractClass {
    abstract thing(): string
}

export class c1 extends abstractClass {
    thing(): string {
        return "greetings"
    }
}

export class c2 extends abstractClass {
    thing(): string {
        return "universe"
    }
}

const cls: CConstructor[] = [c1, c2];

for (const classObj of cls) {
    const c = new (classObj)()
    console.log(c.thing())
}

Update:

The presence of new(): abstractClass within CConstructor denotes a "Construct Signature," which can be created by prefixing a call signature with the keyword new. For further details, refer to the new TS handbook page.

Answer №2

It seems like you are looking to dynamically instantiate your classes. If you need more information on this topic, you can refer to: Dynamic instantiation in JavaScript

For autocompletion, you can cast later to the desired object.

I'm not entirely sure if this will solve your problem, but it might bring you closer to a solution:

interface simpleInter {
  el: string;
}

const cls: simpleInter[] = [];
cls.push({
  el: 'c1'
},{
  el: 'c2'
});

function instantiate(className: string, args: any) {
  var o, f, c;
  c = window[className]; // get reference to class constructor function
  f = function(){}; // dummy function
  f.prototype = c.prototype; // reference same prototype
  o = new f(); // instantiate dummy function to copy prototype properties
  c.apply(o, args); // call class constructor, supplying new object as context
  o.constructor = c; // assign correct constructor (not f)
  return o;
}

for (const classObj of cls) {
  const c = instantiate(classObj.el, []); // error: Cannot create an instance of an abstract class. ts(2511)
  console.log(c.thing());
}

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

Differences between Typescript static methods and functions defined outside of classesWhen comparing Types

What distinguishes a static class method from a function defined outside a class in TypeScript, especially when visibility is not a concern? While there are differences in visibility from other classes and files, what factors should be considered when dec ...

Struggling to locate the module 'firebase-admin/app' - Tips for resolving this issue?

While working with Typescript and firebase-admin for firebase cloud functions, I encountered the error message "Cannot find module 'firebase-admin/app'" when compiling the code with TS. Tried solutions: Reinstalling Dependency Deleting node_modu ...

Can you set up a mechanism to receive notifications for changes in an array variable in Angular?

I'm exploring methods to delay an HTTP request until the user stops interacting. I am considering using the debounceTime() operator from RxJs, but I need this to be triggered by changes in an array that I have defined. Here is the scenario: export c ...

Guide to displaying the continent name on a 3D globe using Reactjs, TypeScript, and Threejs

I am currently working on integrating Threejs into my Nextjs 14 application to create a 3D earth globe using Gltf. However, I am facing an issue where I am unable to display the text of the continent name on their respective continents. I want to have fixe ...

Utilize Function type while preserving generics

Is there a way in Typescript to reference a function type with generics without instantiating them, but rather passing them to be instantiated when the function is called? For instance, consider the following type: type FetchPageData<T> = (client : ...

Exploring TypeScript reflections within a specific namespace

(Building upon previous discussions about dynamically loading a TypeScript class) If I am currently within a namespace, is there a method to reference classes within the namespace in order to utilize 'reflection' to invoke their constructors? n ...

Issue with the comparator class in the STL Set

In my set of IDs (e.g. {3,7,1,5}), I want to ensure that 7 appears before 1 when table[7] < table[1]. My approach to achieve this is as follows: I've created a class named MyClass1, which consists of two members: a vector called table and an oper ...

Appending or removing a row in the P-Table will result in updates to the JSON

My task involves implementing CRUD (Create, Read, Update, Delete) functionality for my table. While Create, Read, and Update are working fine with the JSON file, I am struggling to figure out how to delete a specific row in the table without using JQuery o ...

The angular framework is unable to assign a value to the property 'xxxx' because it is currently undefined

I am currently working on a simple application using Ionic (angular) and I am facing an issue with the error message: Cannot set property 'origin' of undefined Below is the interface for Product.ts: export interface Products{ id: number ...

Combining Rollup, Typescript, and converting images to base64 during the loading process

Having trouble preloading an image with Rollup. None of the solutions that should work seem to be effective, and I can't figure out why. Has anyone successfully managed to make this work? Here is my configuration in rollup.config.js: import image fr ...

Sending an array of data using Angular in a web service

Here is my model object from model.ts name_id: string[]; public generateUrlencodedParameters(token: string, id?: number): string { let urlSearchParams = new URLSearchParams(); urlSearchParams.append('name_id', this.name_id.toS ...

Tips for applying personalized CSS to individual Toast notifications in Angular

MY QUESTION : I am looking to customize the CSS of a single toast used in Angular components. While there may be multiple toasts, I specifically want to style one particular toast differently. For example, the toast image can be viewed here: example toast ...

I am facing a problem with React Hooks useRef where I am unable to retrieve the updated state value

Trying to use useRef with React hooks, I encountered an issue where the state of the child component changes when calling the setAccountVal method, but upon alerting the value it remains as "Ege". Any ideas on how to resolve this? import React, { useS ...

Determining the type relationship between two generic types when using a union

Here is the code snippet defining a React component using react-hook-form: import { type FieldPath, type FieldValues, type FieldPathValue, } from "react-hook-form"; interface FormControlRadioBoxProps< TFieldValues extends FieldValue ...

Guide on incorporating a YouTube iframe in React with Typescript

It appears that Typescript is posing some challenges for me in this scenario. Here's the code snippet I am trying to include: <iframe width="560" height="315" src="https://www.youtube.com/embed/BLAH?showinfo=0" frameBorder="0" ...

Secure Your Passwords with Encryption in NestJS using @nestjs/mongoose before saving them

Seeking to encrypt passwords before saving using @nestjs/mongoose. Came across examples written in pseudocode like this: UsersSchema.pre('save', (next: any) => { if (!this.isModified('password')) return next(); this.password = en ...

The input '{ data: InvitedUser[]; "": any; }' does not match the expected type 'Element'

I'm currently facing a typescript dilemma that requires some assistance. In my project, I have a parent component that passes an array of results to a child component for mapping and displaying the information. Parent Component: import { Table } fr ...

Retrieve the object from the data received from the HTTP GET API call

I have a question that has been asked before, but I am unable to achieve the desired result with my current approach. When my service retrieves data from an API, it returns results in the following format: { "nhits": 581, "paramete ...

How do I add a new item to an object using Ionic 2?

example item: this.advData = { 'title': this.addAdvS2.value.title , 'breadcrumb': this.suggestData.breadcrumb, 'price': this.addAdvS2.value.price ...

Looking for a method to efficiently populate an array with values in Typescript

Here is an example of how I work with arrays in my code: var alphas: string[]; alphas = ['abc1', 'abc2', 'abc3']; // (this array can be changed) My modal class looks like this: export class Team { TeamName: string; } To ...