TypeScript: "Implementing" methods. The organized approach

Currently, I am developing a middleware class for Express. Before delving into the details of the class, it's important to note that I will be injecting the middleware later by creating an instance of my "Authenticator" class and then using its method with

app.use(authInst.express)

The crucial aspect here is the execution context (this) of this function. This is the progress I have made so far:

Option 1

class Authenticator {
    opts: IAuthOpts ;
    express: RequestHandler| ErrorRequestHandler

    constructor(opts: IAuthOpts){
        this.opts = opts;
        this.express = function(req: Request, res: Response, next: NextFunction){

            if(this.opts.enabled) {
                mainController(req, res, next, this.opts)
            } else {
                next();
            }
        }
    }
}

This solution works fine, but I dislike having the function within the constructor as it seems like messy code. Placing the express method directly in the class like this:

Option 2 - Not functioning

class Authenticator {
    opts: IAuthOpts;

    constructor(opts: IAuthOpts){
        this.opts = opts;
    }

    express(req, res, next){
        if(this.opts.enabled) {
            mainController(req, res, next, this.opts)
        } else {
            next();
        }    
    }
}

will not work as the execution context from express will result in 'this' being undefined. Therefore, the following alternative must be considered:

Option 3

class Authenticator {
    opts: IAuthOpts ;
    express: RequestHandler| ErrorRequestHandler

    constructor(opts: IAuthOpts){
        this.opts = opts;
        this.express = _express.bind(this);
    }

    private _express(req, res, next){
        if(this.opts.enabled) {
            mainController(req, res, next, this.opts)
        } else {
            next();
        }    
    }
}

Presently, this solution seems optimal as it enables easy outsourcing of the method to another file while keeping files succinct. However, the downside is the use of bind. Personally, I prefer functions that return the same value when invoked with the same parameters regardless of their origin, which necessitates binding the class each time.

Is there a superior approach for externalizing a method from a TypeScript class without requiring the injection of the execution context via bind?

Answer №1

To replace the bind method, you can opt for an arrow function:

class Authenticator {
    opts:IAuthOpts ;

    constructor(opts:IAuthOpts){
        this.opts = opts;
    }

    express = (req, res, next) => {
        if(this.opts.enabled) {
            mainController(req, res, next, this.opts)
        } else {
            next();
        }    
    }
}

If you decide to move the implementation to a different file, it would be more organized to create a function that accepts the Authenticator as a regular parameter along with req, res, and next, and then invoke that function from your arrow function:

class Authenticator {
    opts:IAuthOpts ;

    constructor(opts:IAuthOpts){
        this.opts = opts;
    }

    express = (req, res, next) => otherFunction(this, req, res, next);
}

// In another file
function otherFunction(authenticator: Authenticator, req: Request, res: Response, next: NextFunction) { 
    if(authenticator.opts.enabled) {
        mainController(req, res, next, authenticator.opts)
    } else {
        next();
    }    
}

If this is not what you had in mind, please provide further clarification on the question.

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

Cannot retrieve authorization cookie

Currently, I am in the process of setting up backend authentication using Express, Node, and Supabase for my frontend built with React. //auth.js import { supabase } from "../config/supabaseConfig.js"; export const checkAuthorizationStatus = asy ...

How can I configure a unique error log format in Winston?

I am facing an issue with the default error log format in Winston, as it includes too much unnecessary information such as date,process,memoryUsage,os,trace. How can I remove these unwanted details from the log? logging.js const express = require('e ...

Creating a method in Angular that combines async/await functionality with Observables

After transitioning from using async/await to Observables in Angular, I am trying to refactor the following code snippet to make it work with Observables: async refreshToken() { const headers = this.authStorage.getRequestHeader(); const body = { ...

Maximizing the Use of Error and Result Data Callbacks Together in Mongoose Express

When trying to utilize error and result data in my controller, I encountered some confusion leading to the following response: { "status": "fail", "message": "Cast to ObjectId failed for value \"60f943dd4bef ...

What steps can be taken to ensure that all object properties become reactive?

Let's dive into this simplified scenario: interface Pup { name: string; age: number; } const puppy: Pup = { name: 'Rex', age: 3, }; The goal here is to establish a reactive link for each attribute within the puppy object. The usua ...

Next.js for the server-side

Today I decided to dive into learning NextJs (React) in order to create a small website for my family. As I progressed through the tutorials on NextJs, it dawned on me that the framework does not natively support server-side rendering, meaning I will need ...

Resolving TS2304 error using Webpack 2 and Angular 2

I have been closely following the angular documentation regarding webpack 2 integration with angular 2. My code can be found on GitHub here, and it is configured using the webpack.dev.js setup. When attempting to run the development build using npm start ...

What is preventing this Node JS code from successfully serving a static PNG file?

To the administrators, I have spent hours scouring various resources for answers related to Node Js, Express, and serving static files. Despite my efforts on stackoverflow and other platforms, I have yet to find any solution that works for me. If my questi ...

The API Gateway LogGroup is experiencing duplication issues and lacks critical details

I've been encountering difficulties setting up CloudWatch logs for my RestApi using cdk. Here is the code I'm using: const logGroup = new LogGroup(this, `apiLogs`, { logGroupName: `apiLogs`, retention: RetentionDays.ONE_WEEK }); ...

Encountered an issue during installation: Error message states that Typings command was not

I've encountered permission errors with npm, so I decided to reinstall it. However, I'm facing an issue with the 'typings' part where it displays a 'typings: command not found' error. This problem seems to be related to Angula ...

Is there a way to determine the quantity of lines within a div using a Vue3 watcher?

Is it feasible to determine the number of text lines in a div without line breaks? I am looking to dynamically display or hide my CTA link based on whether the text is less than or equal to the -webkit-line-clamp value: SCRIPT: const isExpanded = ref(true ...

Node.js Express JS is currently in the process of retrieving a file

I'm currently grappling with an issue while attempting to download a file using express js. Here is the function in question: var download = function(uri, filename, callback) { request .get(uri) .on('response', function (response) { ...

Exploring the Power of Node.JS in Asynchronous Communication

Hey there, I'm not here to talk about async/await or asynchronous programming - I've got that covered. What I really want to know is if it's possible to do something specific within a Node.js Express service. The Situation I've built ...

No content displaying after deploying React/Node app on Replit or Heroku

Currently, I am developing an ecommerce service using React and NodeJS/Express. While I have successfully deployed my project on Replit, I am facing an issue where it only works on my local server. On other devices, the screen remains blank. I suspect that ...

typescript library experiencing issues with invalid regex flags in javascript nodes

I am facing an issue while attempting to import a plain JavaScript module into a Node application written in TypeScript. The error below is being thrown by one of the codes in the JavaScript module. b = s.matchAll(/<FILE_INCLUDE [^>]+>/gid); Synta ...

Performing data manipulation in MongoDB using Node.js, Express, and Mongoose

import mongoose from "mongoose"; const productSchema = mongoose.Schema( { name: { type: String, required: true }, category: { type: mongoose.Schema.Types.ObjectId, ref: "Category" ...

Exploring the functionalities of arrays in Typescript: A beginner's guide

Currently, I am working on a react project and building a store within it. Below is the code snippet I have implemented: import React, { useReducer, useEffect } from 'react'; import { v4 as uuid } from 'uuid'; import { Movie, MoviesAct ...

Is it possible to use a hyperlink in Node.js to transmit information to an API using an Express request?

I am working on an HTML page where I need to send data to an API when a specific link is clicked. To achieve this, I am using Express along with a form that has a POST method. Here is the link: <form action="/bx/processed-manually" method=&qu ...

Issues encountered while attempting to update data in angular2-datatable

Once the datatable has been rendered, I am facing an issue where I cannot update the data. I'm utilizing angular2-datatable. In my appcomponent.html file: If I try to update 'data2' in my appcomponent.ts file as shown below: this.httpserv ...

Using @Input to pass data from a parent component to a

Looking to modularize the form code into a separate component for reusability? Consider using @Input and referencing it in the HTML to pass values to the post method. Here's how you can achieve this: Previously, everything worked smoothly when all th ...