What is the best way to instantiate a class that is stored within a variable of an abstract class?

While working on a TypeScript project for fun, I encountered a fascinating scenario where I couldn't instantiate a reference to a class. This issue arose because TypeScript seemed to assume it was an instance of the class.

const programClass: Program = this.fetchProgram(programName) as Program

The function fetchProgram retrieves a program class from a map that dynamically loads each program from files.

An example of how the map is initialized:

const programPath = "../../../programs"
const programFiles = fs.readdirSync(path.join(__dirname, programPath))

programFiles.forEach(file => {
  file = path.join(__dirname, programPath, file)
  const cmdClass = require(file).default
  const command = new cmdClass() as Program
  this.commands.set(command.alias, command)
})

Each individual "program" is a file that exports a class extending the abstract class program.

Example program:

export default class ProgramEcho extends Program {
  alias = "echo"
  constructor(options: ProgramOptions) {
    super(options)
    console.log(`DEBUG: Program Instantiated: Echo`)
  }
}

Returning to the initial code snippet, it becomes apparent that it's treated as an instance of Program, when in reality, it should be a constructable class which extends Program.

const programClass: Program = this.fetchProgram(programName) as Program
const program = new programClass()

error:

const programClass: Program
This expression is not constructable.
  Type 'Program' has no construct signatures.ts(2351)

It seems like one could implement a simple factory pattern where the abstract class program includes a method called create that returns a new Program. However, returning an instance of an abstract class is not possible here.

Answer №1

Upon closer examination, it becomes evident that the Program type pertains to an instance of the Program class. What is needed is a constructor capable of generating a new Program instance. If all your Program subclasses share the same constructor arguments, the appropriate type declaration would be:

type ProgramCreator = new (options: ProgramOptions) => Program;

This definition enables the creation of an instance as follows:

const programConstructor: ProgramCreator = this.fetchProgram(programName) as ProgramCreator;
const options: ProgramOptions = ??? // origin unknown
const program = new programConstructor(options);

Explore Typescript Playground

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

Steps for leveraging pdfMake with live data

Recently delving into Angular, I've been exploring the capabilities of pdfMake. While I successfully incorporated static data, I'm facing challenges when attempting to utilize dynamic data. Any guidance on how to achieve this would be greatly app ...

The 'Set-Cookie' response header failed to be recognized for a subsequent HTTP request

When a user successfully logs in, their information is stored in a cookie using the "Set-Cookie" response header. However, I am facing an issue where the cookie seems to get lost when making subsequent requests from the client. As a result, the server trea ...

Creating a wrapper for methods of a third-party class in TypeScript

I have been working on creating a wrapper for all my third party API interfaces and SDKs that logs requests in a standardized yet customizable way. My approach involves passing the third party API (typically instantiated with a new API() call) into a wrapp ...

Having trouble importing an object from another file in Typescript?

I'm facing a peculiar issue where I am unable to import a const declared in one file into another file. When trying to import the const, a TS error pops up stating Module '"../resources/dummy_container"' has no exported member &apo ...

NestJS TypeORM InjectRepository throwing an error: "Cannot access property 'prototype' of undefined"

Encountering an issue while trying to unit test. Here is the error message that I received: TypeError: Cannot read property 'prototype' of undefined export class UserService { constructor(@InjectRepository(User) private readonly userRepository ...

Compiling problem encountered in Typescript due to error TS2705 related to the ES2015 --lib option

When I run tsc -p . to compile a TypeScript file, I encounter the following error: error TS2705: A async function or method in ES5/ES3 requires the 'Promise' constructor. Make sure you have a declaration for the 'Promise' constructor o ...

What is the syntax for declaring a state variable as a Set data type in programming?

Struggling to establish a state variable in React using Typescript. Encountering an error when attempting to specify its type as Set. The purpose of this variable is to contain an array of objects. const [blocksList, setBlocksList] = useState<Set>([ ...

methods for closing dialog box without altering UI in angular

I have a list of charts on my workspace page and have implemented a Delete confirmation dialog box for when I want to delete a selected chart. However, I have encountered a strange issue where when the delete dialog box is open and I click the cancel butt ...

When using Typescript, ENUMs can be passed as interface values without any issues. However, errors may occur

To ensure consistency in sizes and colors within my UI library, I decided to create an ENUM for each value. export enum sizes { small = 'small', medium = 'medium', large = 'large', } export enum colors { orange = ...

Enhance the visual appeal of your checkboxes in React Fluent UI by customizing the color of the checked mark and

I have a React application using Fluent UI. Currently, the <Checkbox/> component is displaying with its default colors and behavior like this: https://i.sstatic.net/ZSL7I.png I want to customize the color of the checked mark and label (Green for ch ...

The ESlint extension in VScode encountered compatibility issues on the MacBook Pro 2021 powered by the Apple M1 Pro chip

After using eslint in vscode on Apple M1 Pro chips, I encountered an issue. I was able to execute eslint via the command line without any problems: > eslint app.js /playground/nodejs/eslint-demo/app.js 1:7 error 'a' is assigned a value ...

Modifying the response header in a node.js middleware: A step-by-step guide

I've been researching this question extensively on Google, but unfortunately, none of the solutions seem to work for me. The issue I'm facing is related to adding a specific property to the response header called "isAuth," which needs to be set ...

Is it possible to modify the output type of a function depending on a parameter's characteristic?

In my code, I have a custom utility function that wraps document.querySelector function querySelector<T extends HTMLElement>(selector: string) { return document.querySelector<T>(selector); } I modified it to include an option to throw an e ...

Can you divide and repurpose several function overloads in TypeScript?

I've put together this sandbox of code In my project, there are 2 functions named slice in separate classes. They both contain a lengthy and repetitive set of overrides: export class Atom<S> { constructor(private initial: S) { } // Se ...

Here is a guide on sorting through data within an array of objects using React.js and Typescript

How can I filter dealers' data based on the minimum and maximum price range of a slider change? I am retrieving dealers' data using an API and storing the slider's min and max values in a handle change function. What is the best way to filte ...

Implementing Microdata with React and Typescript: A Comprehensive Guide

Whenever I include itemscope itemtype="http://schema.org/Product" in h1, an error pops up: The type '{ children: string; itemscope: true; itemtype: string; }' is not compatible with the type 'DetailedHTMLProps<HTMLAttributes<HTMLH ...

How does the nonempty assertion of TS impact the inference of function generics?

My definition of the type and the variable is as follows: the LOCALES_KEYS variable is an enum export const resources = { 'ja-JP': jaJP, 'zh-TW': zhTW, 'en-US': enUS, 'zh-CN': zhCN, }; export type Lng = key ...

I am searching for answers to solve issues related to a JSON file

I am currently working on a tool that searches for matches in an input field by comparing the keywords entered by the user with a JSON. During my testing phase, I focused on using a single API that provides information about different countries and fortun ...

Unable to associate a model with an additional attribute in objection because of a TypeScript issue

I'm attempting to establish a connection between two models while adding an additional property called "url": if (typeof session.id === "number") { const sessionUser = await Session.relatedQuery("users") .for(session.id) .relate({ id: ...

Can we expect Karma to receive updates for upcoming versions of Angular and Jasmine?

We recently attempted to upgrade our company's Angular module, which required updating dependencies as well. Upon upgrading to the latest versions, we encountered an issue with the Jasmine-karma-HTML-Reporter due to its reliance on Jasmine-core 4.x.x ...