What is the best way to call a method within a TypeScript class using its name as a string while already inside the class itself?

Currently, I am developing a class that automates the creation of routes for Express and invokes a function in a controller. However, upon trying to execute this[methodName](req, res), I come across an error message stating: 'Element implicitly has an 'any' type because an expression of type 'string' cannot be used to index type 'AbstractActionController'. No index signature with a parameter of type 'string' was found on type 'AbstractActionController'.ts(7053).' Despite extensive research, I have yet to find a solution. I suspect that specifying types is necessary, but the method eludes me.

import AbstractActionControllerInterface from './interfaces/AbstractActionControllerInterface'
import { Application, Request, Response } from 'express'

class AbstractActionController implements AbstractActionControllerInterface {
    public alias: string
    private app: Application

    constructor(alias: string, app: Application) {
        this.alias = alias === 'index' ? '' : alias
        this.app = app

        this.registerActionRoutes()
    }

    /**
     * registerActionRoutes
     *
     * Function to log the routes with Action indicator in a controller.
     */

    private registerActionRoutes() {
        const classMethods = Object.getOwnPropertyNames(
            Object.getPrototypeOf(this),
        )

        for (const methodName of classMethods) {
            if (methodName !== 'constructor' && methodName.includes('Action')) {
                let route = methodName.split('Action')[0]

                route = route === 'index' ? '' : route

                this.app.all(
                    `${this.alias}/${route}`,
                    (req: Request, rep: Response) => {
                        if (typeof this[methodName] === 'function') {
                            this[methodName](req, rep)
                        }
                    },
                )

                console.log(
                    `[Lua]\x1b[33m Route ${this.alias}/${route} attached. \x1b[0m`,
                )
            }
        }
    }
}

export default AbstractActionController

I attempted using [key: string]: any in typing, but this lacks indexes 🤔🤔 perhaps there's knowledge I'm missing.

Answer â„–1

If you want to refine the type of your action function, consider using a type predicate (formerly known as user-defined type guards).

Here's a straightforward example of how you can narrow your function:

function isActionFunction(fn: any): fn is (req: Request, res: Response) => void {
    return typeof fn === 'function';
}

Below is an updated version of your code demonstrating the use of this approach in context:

import { Application, Request, Response } from 'express'

function isActionFunction(fn: any): fn is (req: Request, res: Response) => void {
    return typeof fn === 'function';
}

class AbstractActionController {
    public alias: string
    private app: Application

    constructor(alias: string, app: Application) {
        this.alias = alias === 'index' ? '' : alias
        this.app = app

        this.registerActionRoutes()
    }

    /**
     * registerActionRoutes
     *
     * Logs routes with Action indicator in a controller.
     */

    private registerActionRoutes() {
        const classMethods = Object.getOwnPropertyNames(
            Object.getPrototypeOf(this),
        ) as Array<keyof typeof this & string>;

        for (const methodName of classMethods) {
            if (methodName.endsWith('Action')) {
                let route = methodName.split('Action')[0]

                route = route === 'index' ? '' : route

                this.app.all(
                    `${this.alias}/${route}`,
                    (req: Request, rep: Response) => {
                        const fn = this[methodName];
                        if (isActionFunction(fn)) {
                            fn(req, rep)
                        }
                    },
                )

                console.log(
                    `[Lua]\x1b[33m Route ${this.alias}/${route} attached. \x1b[0m`,
                )
            }
        }
    }
}

export default AbstractActionController

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

Obtaining the request URL in a Firebase Cloud function

Currently, I have two Angular applications that are both connected to the same Firebase/Firestore instance: I have successfully integrated Firebase Cloud Functions with Express. However, I am facing a challenge where I want to selectively manipulate the d ...

I am attempting to incorporate a data layer into kepler.gl using react, however, the data layer is not appearing

I'm facing an issue while attempting to programmatically add a cluster layer in kepler.gl map. Even after dispatching the data on the map, I am unable to view any layers. Any assistance with this problem would be greatly appreciated. dispatch( ...

Tips for utilizing a personalized technique on an array

Can you explain why a custom method on an array is not functioning properly in this scenario? function runTestMethod() { alert("method running"); } String.prototype.testMethod = runTestMethod; var A = "A"; A = A.testMethod(); // This works ...

Exploring the Variance between 'npm run serve' and 'npm run dev' Commands in Vue.js Development

Can you explain to me the distinction between npm run serve and npm run dev in vuejs? Additionally, can you clarify why it is recommended to use the npm run serve command when running a project? ...

Combine two arrays of data sources

mergeThreads() { const userId = this.auth.getUser().uid; const buyerThreads$ = this.afs.collection('threads', ref => ref.where('buyerId', '==', userId)).valueChanges(); const sellerThreads$ = this.afs.collection ...

What is the process for integrating a library into karma tests?

During my tests, I encountered an issue with using external libraries. I have added all the necessary links in karma.conf.js and some libraries were included successfully. However, for certain libraries, Karma seems to set "undefined" instead of "this" whe ...

JavaScript allows for the creation of animated or timed text

Here is the code snippet I am currently working with: function list() { return "blob1<br>blob2<br>blob3"; } When I run this code, it simply displays all the text in return at once when the function is called. I am wondering if there is a ...

Retrieving the checkbox value from a dropdown selection

I'm stuck and feeling lost here - I must be missing something obvious. Any help will be greatly appreciated! (I am a beginner in html and javascript) I have created a dropdown menu with an unordered list of items populated from JSON data. Here is the ...

Validate that the input is an array

Looking for a way to determine if a function parameter is an array or not, and then process it accordingly. If the parameter is not an array, convert it into an array before performing the desired function. For example: interface employee { first: st ...

Can we improve the coding of this as it seems inefficient and uses up too much room?

Do you think there is a more efficient way to write this code? It seems quite impractical and takes up a lot of space. Essentially, it's about the random chance of obtaining a rarity, like acquiring an Uncommon sword. if (Math.random() * 100 < 100 ...

Error in Angular 8: The type of '[object Object]' is an object, whereas NgFor only supports binding to Iterables such as Arrays

I recently started using Angular 8 and I'm dealing with an issue while trying to fetch data from an http get request. I am attempting to iterate through the data using *ngFor but unfortunately encountering this error. Any suggestions on how to resolv ...

"Maximizing Efficiency: Chaining Several Actions Using the JavaScript Ternary Operator

When the condition is true, how can I chain two operations together? a = 96 c = 0 a > 50 ? c += 1 && console.log('passed') : console.log('try more') I attempted chaining with && and it successfully worked in react, b ...

Sorting Mongoose responses based on a specified schema

I am seeking assistance on how to sort response data based on a schema. Here is my schema const RoleModel = new Schema({ name : {... }, description:{... }, permission:{... } },{timestamps: false}) and here is my current respons ...

Encountering a Laravel Nova issue where attempting to override a Vue component leads to a Vue warning: Error

Recently, I decided to incorporate a user guide into my nova using the following Vue Shepherd library. To make this work, I made some adjustments in the files within the nova directory. One of these changes involved renaming the file "webpack.mix.js.dist" ...

How can I turn off automatic ellipsis on my IOS device?

Currently, I am working on a web application that involves displaying location descriptions retrieved from an API. The issue I am encountering is that the description is being cut off with an ellipsis after a certain number of lines when viewed on an iPhon ...

Automated Copy and Paste Feature - JavaScript using Ajax

I am working on a unique auto-increment IMDB ID grabber that retrieves the ID as you type the name of a TV show. Currently, I have managed to create functionality where it checks if the field is empty; if not, it displays a button that directs you to a pag ...

Javascript error - SyntaxError: unexpected token '}' after property list is missing

In my code snippet below: var UserCharacter = { UserID: util.getCookie('u_u'); userUsingThisCharacter: function() { var data = {}; data.UserID = UserCharacter.UserID; $.ajax({ type: "GET", url: util.API_URL + "charact ...

The ng-message function appears to be malfunctioning

I am facing an issue with the angularjs ng-message not working in my code snippet. You can view the code on JSfiddle <div ng-app="app" ng-controller="myctrl"> <form name="myform" novalidate> error: {{myform.definition.$error ...

Creating interactive JavaScript elements that can be moved around within a container

I recently faced a challenge while attempting to make draggable elements within a div. The issue arose when I realized that I couldn't figure out how to drag each element individually without affecting the others. My current code only allows for handl ...

Adjust the background color using jQuery to its original hue

While working on a webpage, I am implementing a menu that changes its background color upon being clicked using jQuery. Currently, my focus is on refining the functionality of the menu itself. However, I've encountered an issue - once I click on a men ...