When utilizing a property on "this" within a function defined in a constructor, the compiled JavaScript code produces an undefined result

Currently, I am in the process of creating a prototype where my objective is to develop a webservice using the express framework in TypeScript, compile it to TS, and host it within a firebase functions environment. The code structure includes a Controller layer and a business logic layer, similar to what you would find in a .Net webservice. By utilizing dependency injection with the inversifyJS framework, I am able to inject the logic class into the controller.

Below is a snippet of the TypeScript code that has been written so far:


            @injectable()
            export class Service1Controller extends ApiController implements IService1Controller {
                public constructor(
                    @inject(TYPES.IService1Logic)
                    private service1Logic: IService1Logic
                ) { super() }

                private fastGet(request: Request, response: Response) {
                    const original = request.query.text;
                    const changed = this.service1Logic.UpdateFastGet(original);
                    response.status(200).send(changed);    
                }
            
        

And this is a portion of the compiled output for the Controller code:


                constructor(service1Logic) {
                    super();
                    this.service1Logic = service1Logic;
                }
                fastGet(request, response) {
                    const original = request.query.text;
                    const changed = this.service1Logic.UpdateFastGet(original);
                    response.status(200).send(changed);
                }
            
        

When testing the code locally using the firebase functions emulator, I encounter an error where the property service1Logic is unable to be read from undefined. It appears that this is undefined and I have been unable to pinpoint the cause of this issue.

I have attempted to reproduce the error with the following code:


                @injectable()
                export class Class1 extends baseClass implements Interface1 {

                    constructor(
                        @inject(TYPES.Interface2)
                        private class2: Interface2
                    ) { super() }

                    PrintText(text: string): void {
                        const mutatedText: string = this.class2.MutateText(text);
                        console.log(mutatedText);
                    }

                    Addition(x: number, y: number): number {
                        return this.Sum(x, y);
                    }
                
            

The controller compiled code appears nearly identical:


                    let Class1 = class Class1 extends baseclass_1.baseClass {
                        constructor(class2) {
                            super();
                            this.class2 = class2;
                        }
                        PrintText(text) {
                            const mutatedText = this.class2.MutateText(text);
                            console.log(mutatedText);
                        }
                        Addition(x, y) {
                            return this.Sum(x, y);
                        }
                    };
                
            

Running this code outside of the emulator, using node, does not yield any errors. It seems that 'this' in PrintText does indeed exist. I even copied the tsconfig.json content from the original project to the error-isolating project, but the issue persists. I am currently at a standstill and am unable to determine the root cause of the error. Has anyone encountered a similar issue or knows how to resolve it?

Edit: Added the calling code

In the prototype code, the methods are linked to a route.


                    app.get('/fastget', this.fastGet);
                
            

The 'App' is of type Express:


                    this.app = express();
                
            

and 'App' is returned via a getter in the ApiController and is then added to the onRequest of firebase:


                    const service1Controller: IService1Controller = container.get<TYPES.IService1Controller>(TYPES.IService1Controller);

                    export const service1 =  functionsEUWest1.https.onRequest(service1Controller.App); 
                
            

Below are the 'Types' and 'Container' objects:

Types.ts


                    let TYPES = {
                        //Controllers
                        IService1Controller: Symbol("IService1Controller"),

                        //BusinessLogics        
                        IService1Logic: Symbol("IService1Logic")
                    }

                    export default TYPES;
                
            

inversify.config.ts


                    class ContainerConfig {
                        private _container: Container = new Container;

                        get Container() { return this._container };

                        private configureControllers(container: Container) {
                            container.bind(TYPES.IService1Controller).to(Service1Controller);
                        }

                        private configureBusinessLogics(container: Container) {
                            container.bind(TYPES.IService1Logic).to(Service1Logic);
                        }

                        constructor() {
                            this.configureControllers(this._container);
                            this.configureBusinessLogics(this._container);
                        }
                    }

                    export default new ContainerConfig().Container;
                
            

For the error-isolating code, the calling code is as follows:


                    const class1: Interface1 = container.get<Interface1>(TYPES.Interface1);

                    class1.PrintText("This text is");
                    const result = class1.Addition(2, 3);

                    console.log(`Sum of 2 and 3 is ${result}`);
                
            

This is how the 'TYPES' and 'Container' objects are defined:

Types.ts


                    let TYPES = {
                        Interface1: Symbol("Interface1"),
                        Interface2: Symbol("Interface2")
                    }

                    export default TYPES;
                
            

intensify.config.ts


                    const container = new Container();

                    container.bind(TYPES.Interface1).to(Class1);
                    container.bind(TYPES.Interface2).to(Class2);

                    export default container;
                
            

Answer №1

Upon further investigation, it was discovered that when passing a handler to app.get, the context of 'this' in the class where the handler is implemented becomes unknown. Delving deeper into this issue, a relevant topic was uncovered:

Express JS 'this' undefined after routing with app.get(..)

It was found that using .bind can help solve this problem. The solution involves binding 'this' to fastget:

 app.get('/fastget', this.fastGet.bind(this));

By implementing this change, the handler now works as expected.

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

Typing Redux Thunk with middleware in TypeScript: A comprehensive guide

I recently integrated Redux into my SPFx webpart (using TypeScript), and everything seems to be working fine. However, I'm struggling with typing the thunk functions and could use some guidance on how to properly type them. Here's an example of ...

When trying to reload Angular 8 pages, encountering an error that reads "Cannot GET /login" and also receiving a notification stating the image '/favicon.ico' cannot be loaded due to a violation of

Encountering an issue with the error message "Cannot GET login/" appearing on the page body of my latest Angular 8 app. Despite attempting various solutions found on forums, I have been unable to resolve this error. Any suggestions or advice would be great ...

Using Angular (along with Typescript) to showcase JSON data

I previously shared this query, but unfortunately, I didn't receive many helpful responses I have a JSON file that holds the following dataset: [{ "ID": 1030980, "Component": "Glikoza (Gluk)", "Result": "16", "Date": "20.10.2018" } ...

Is it possible to determine if an HTML form has been modified?

Is there a way in typescript to determine if a form has been changed and return true or false accordingly? For example, if I have a first name field with the current value of "John" and then change it to "Johny", it should return true. But if I revert it b ...

What should I do when dealing with multiple submit buttons in NextJS?

How can I differentiate between two submit buttons in a form component created in Next.js? I'm struggling to determine which button was pressed and need help resolving this issue. import React from "react"; const LoginPage = () => { as ...

Retrieving JSON data from Firebase and transforming it into an array containing identical values [Swift]

Recently, I've been working with a JSON database in Firebase that looks something like the snippet below: "Trips" : { "-KnH34F_WZYNHMsTzj0X" : { "Distance" : 500, "Transport" : "Walk", "TripName" : "Work" ...

Is it possible to iterate through TypeScript using both keys and indexes?

Explained in detail at this link, TypeScript introduces a foreach loop: let someArray = [9, 2, 5]; for (let item of someArray) { console.log(item); // 9,2,5 } However, is there a way to access the index/key? I was thinking something along the lines of ...

JavaScript's Blob to Base64 conversion using FileReader is failing to produce any output

In my typescript application, I am utilizing the FileReader to convert a blob into a base64 image for display within the template. adaptResultToBase64(res: Blob): string { let imageToDisplay : string | ArrayBuffer | null = ''; const re ...

I want my Angular 2 application to redirect to the appropriate page when a user who is logged out attempts to access a page that requires them to be logged in

When a user is logged out in Angular 2 router and they try to navigate to a page that requires them to be logged in, I need the app.ts file to redirect them. I am utilizing typescript along with angular 2. Oddly enough, the redirection works for certain ...

Unable to allocate FormArray

Just delved into learning Angular and encountered a snag. I am trying to add and remove textfields for a form, so I attempted the following code in my component.ts file: import {FormBuilder, FormGroup, FormArray } from '@angular/forms'; This is ...

How to Change the Checked State of a Checkbox in React Material UI

I am faced with a situation where I have multiple checkboxes that are used to toggle table columns on and off. The code snippet demonstrates how it looks: const [fields, setFields] = useState<Set<string>>(new Set(["name"])); const ...

Measuring Feedback: Utilizing Angular 4 to calculate review ratings

I'm facing a challenge while working on a review form using Firebase and Angular 4. The issue is with calculating the total length of added reviews and the sum of their ratings. Each time a new review is submitted, it gets pushed to a list of objects ...

How can a property be made mandatory in Typescript when another property is set as optional?

Currently, I am unsure about what to search for in order to fulfill the following requirement. Specifically, I am utilizing the given type for react props: interface ComponentProps { message : string, minValue? : number, minValueValidationMessage? ...

Is there a way to retrieve a compilation of custom directives that have been implemented on the Vue 3 component?

Is there a way to retrieve the list of custom directives applied to a component? When using the getCurrentInstance method, the directives property is null for the current component. I was expecting to see 'highlight' listed. How can I access the ...

Struggling with consolidating values in an array of objects - seeking assistance with Javascript

Currently, I am handling a project where I receive data in the form of an Object Array. My task is to merge values with the same key into one key and convert the values into an array of strings. Below is the sample data I am working with: inputArray = [ ...

Issue with Datatables not loading on page reload within an Angular 7 application

Incorporating jQuery.dataTables into my Angular 7 project was a success. I installed all the necessary node modules, configured them accordingly, and added the required files to the angular.json file. Everything functioned perfectly after the initial launc ...

What is the best way to securely store a sensitive Stripe key variable in an Angular application?

When implementing Stripe payment system in my Angular App, I often wonder about the security of storing the key directly in the code as shown below. Is this method secure enough or should I consider a more robust approach? var handler = (<any>windo ...

Encountering a SyntaxError while utilizing framer-motion in Next JS

Currently, I am working with NextJS version 12.0.3 and integrating framer motion for animations into my project. However, regardless of the framer-motion library's capabilities, whenever I add a tag to any HTML element in my component, an error is tri ...

Using a specific type of keys, attempting to set two instances of those keys simultaneously will result in an error of that type

Consider this scenario: type Example = { x: string, y: number } const a: Example = { x: "x", y: 1 } const b: Example = { x: "y", y: 2 } const issue = (keys: (keyof Example)[]) => { keys.forEach(key => { a[key] ...

Tips for locating precise information within nested object formations using Javascript

Within my code, I have showcased two distinct types of response. Upon closer examination of the following code snippets, it becomes evident that the structure of the response from a service differs slightly between the two types. In the first type, there i ...