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.