A guide on generating instances from classes located in a directory with typescript

Imagine a scenario where there is a directory structure like the one below:

Shapes/
  Square.ts
  Circle.ts
  Rectangle.ts

The objective here is to create a data structure, either a Map or an object, where the filename (without the extension) serves as the key and the corresponding class within the file acts as the value. This will allow for easy initialization using the new keyword.

For instance:

import Application from './Application' // This would be the entry point of the application

let instances: Map<string, Shape> = Application.getShapes() // The 'getShapes' should return a Map with the specified format.

let square = new instanes.get("Square") // Expectation is to instantiate a Square object

The goal here is to move away from manually creating instances and instead dynamically generate them.

import AlnumRule from './Rules/AlnumRule'
import Rule from './Rules/Contracts/Rule'
import RequiredRule from './Rules/RequiredRule'

export default class RulesMapper {
  static map: { [index: string]: Rule } = {
    required: new RequiredRule(),
    alnum: new AlnumRule(),
  }

  static resolve(rule: string): Rule {
    return RulesMapper.map[rule]
  }
}

To put it simply, the aim is to scan all files within a specific directory, extract the constructible classes, and then store them in either an object or a Map for future use.

Answer №1

This scenario assumes that your system supports dynamic import capabilities (such as Node.js with CommonJS or ES modules). It's important to note that utilizing dynamic imports can add complexity, so be mindful of potential security risks, particularly if the input for importAndInitializeClasses is not sanitized.

Make sure to customize the code based on your specific requirements and setup.

// Application.ts
import { readdirSync } from 'fs';
import { basename, join } from 'path';

// Function to dynamically import and initialize classes
async function importAndInitializeClasses<T>(directory: string, fileExtension: string): Promise<Map<string, T>> {
  const instances = new Map<string, T>();
  const files = readdirSync(directory).filter(file => file.endsWith(fileExtension));

  for (const file of files) {
    const className = basename(file, fileExtension);
    const filePath = join(directory, file);
    const module = await import(filePath);
    const classInstance = new module[className]();
    instances.set(className, classInstance);
  }

  return instances;
}

export default class Application {
  static async getShapes(): Promise<Map<string, unknown>> {
    return importAndInitializeClasses<unknown>('Shapes', '.ts');
  }
}

// Implementation in a different file
import Application from './Application';

async function main() {
  const instances = await Application.getShapes();
  const square = new (instances.get('Square'))(); // Dynamically instantiate Square
  // ...
}

main();

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

Turn off TypeScript's type validation during production builds

For my petite project, I am utilizing Next.js with TypeScript. A thought has been lingering in my mind lately: is there a way to turn off the types validity checks while executing npm run build? Since the type checking occurs during npm run dev, it seems ...

Implementing MouseEvents in Typescript React without having to pass them down to child elements

Is it possible to use Mouse Events on a whole React Element without having to pass it to a child element? I have been passing my handleEvent function to several functional components and now I want to know if it can be done without causing a TypeScript err ...

When working with Angular 12, the target environment lacks support for dynamic import() syntax. Therefore, utilizing external type 'module' within a script is not feasible

My current issue involves using dynamic import code to bring in a js library during runtime: export class AuthService { constructor() { import('https://apis.google.com/js/platform.js').then(result => { console.log(resul ...

Implementing conditional where clauses in Firestore queries with dynamic parameters

Consider this scenario: I have a dynamic filter list for my product list, and I want to send an HTTPS request to a cloud function based on the selected filters. However, when trying to set multiple conditional where clauses from that request... The multip ...

What exactly does ".default" signify in Angular, Typescript, or Javascript?

Could someone please clarify the significance of the ".default" in the code snippet below? I am interested in implementing this code in our project, but my understanding of the mentioned code fragment is uncertain. (I have modified my question to display ...

The continuous invocation of the ngStyle background-image in Angular 4 is causing a decrease in the loading speed of the page

I'm currently working on an Angular CLI Project "@angular/cli": "^1.1.1", "@angular/compiler-cli": "^4.0.0", In order to dynamically load images from the assets folder within an ng-for loop, I am using the following line of code: [ngStyle]="{&a ...

What is the proper way to utilize queries in BlitzJS?

I am attempting to extract data from a table by filtering based on the relationship with the Blitzjs framework. However, I am facing difficulties using queries as it seems to be the only option available. Every time I try to call the quer ...

Issue with React.js code not being detected in TSX file (Visual Studio 2015 Update 1 RC)

Currently, I am utilizing Visual Studio 2015 with update 1 release candidate. Interestingly, I have managed to successfully incorporate React.js code and syntax highlighting within a .JSX file. However, when it comes to a .TSX file, nothing seems to be wor ...

What is the correct way to integrate nested forms using Validator and Control Value Accessor?

One challenge in my application is the need for a reusable nested form component like Address. I wanted my AddressComponent to manage its own FormGroup without the need for external input. During an Angular conference (video, presentation), Kara Erikson f ...

Tips for restricting keys when using a union as an indexer without demanding all of them

Trying to create a type that only allows certain keys from a union using the key in statement has resulted in all keys being required. How can I define this type so that not all values have to be present? const widgetOptions = ['option1', 'o ...

Chaining Assignments in TypeScript

let a: { m?: string }; let b = a = {}; b.m = ''; // Property 'm' does not exist on type '{}'. let a: { m?: string } = {}; let b = a; b.m = ''; // It's OK Link to TypeScript Playground What occurs ...

Issue with API and Middleware: unable to access /api/auth/providers

Currently, I am following an educational video tutorial on Next Auth V5. Despite being a beginner in coding, I am doing my best to keep up. I am currently stuck at 2 hours, 9 minutes, and 45 seconds into the 8-hour-long video. The issue arises during th ...

Filter an array of objects in Angular2 based on properties that are not included in the specified values

I'm encountering some difficulties while filtering an array of objects based on a specific set of values: Here is the array that needs to be filtered: const items: Product[] = ... values Next, I have created an array containing the products that I w ...

Is there a way to convert my messages into different languages without relying on the 'translate' directive or pipe?

Currently, my Angular application is set up with ngx-translate for translation purposes. While it is currently monolingual, I am already looking ahead to the possibility of needing to translate it in the future. Everything is functioning perfectly, but I w ...

Updating the array in React state does not work properly

Update: Visit the Snack Expo for the latest version. I have a page that displays a list. When I click on a Delete button, my goal is to remove the item with a specific id from the list. The code snippet is shown below: import { useState, memo, useCallbac ...

Setting Max or Min Date to Today for Date Input in Angular 2 and Ionic 2

<input class="alert-input date-input" #dob="ngModel" name="dob" max="2018-03-07" [(ngModel)]="leadDetail.dob" type="date"></div> Is there a way to dynamically set the max date to today instead of 2018-03-07? I have tried a couple of methods b ...

The frontend is not triggering the Patch API call

I am having trouble with my http.patch request not being called to the backend. This issue only occurs when I try calling it from the frontend. Oddly enough, when I tested it in Postman, everything worked perfectly. Testing the backend on its own shows t ...

Typescript: Error encountered. Invalid input: Non-string value provided to `ts.resolveTypeReferenceDirective`

A while back, I developed an npm command line application that was working perfectly fine. However, after a recent update due to changes in TypeScript versions over time, I encountered an error when trying to run the package. The error message I received w ...

Guide on creating a Typescript Conditional type structure for Array elements that rely on each other

In my function, I am working with an array of objects that contain an icon key. If one index in the array has a value assigned to the icon key, then another index should also have a value. If one index leaves the icon key undefined, then another index shou ...

Issue: Incorrect hook usage. Hooks are designed to be used within the body of a function component. This error may occur due to one of the following reasons: 1

I've reviewed similar questions and attempted to apply the solutions provided, but it seems I'm missing something specific to my situation. My goal is to streamline my code by importing headers from a utils file and using them across different AP ...