Properties of a child class are unable to be set from the constructor of the parent class

In my current Next.js project, I am utilizing the following code snippet and experiencing an issue where only n1 is logged:

class A { // A: Model
    constructor(source){
        Object.keys(source)
        .forEach(key => {
            if(!this[key]){
                this[key] = source[key];
            }
        });
    }
}

class B extends A{ // B: User
    first_name: string;
}

let v = new B({first_name: "nof"});
console.log(v)
// B { first_name: undefined }

Strangely enough, when I use this code in a non-Next.js project, both n1 and n2 are displayed. It seems like there may be some configurations within Next.js causing this discrepancy. Any suggestions on how to achieve consistent behavior without declaring a constructor in the B class?


The original example for reference:

class A {
    constructor(){
        this.init()
    }
    init(){
        this["n1"] = "nof";
        this["n2"] = "nof";
    }
}

class B extends A{
    n1: string;
}

let v = new B();
console.log(v)
// B { n1: undefined, n2: 'foo' }

Answer №1

The outcome meets expectations. When creating a fresh instance of B, it initiates the creation of A first so that both n1 and n2 are initialized as 'nof'. Subsequently, B is created and replaces n1 with an unset (typically undefined) variable, resulting in n1 = undefined while n2 should remain as 'nof'.

Answer №2

The change in behavior you are experiencing is likely due to the useDefineForClassFields setting being enabled now, whereas it was disabled before. According to the provided link:

Use Define For Class Fields - useDefineForClassFields

This flag is used when transitioning to the new standard version of class fields. TypeScript implemented class fields long before they were officially approved by TC39. The latest version of the upcoming specification has a different runtime behavior compared to TypeScript’s implementation but uses the same syntax.

This flag aligns with the upcoming ECMA runtime behavior.

You can find more information about this transition in the 3.7 release notes.

Essentially, after the constructor for A finishes running, the (implicit) constructor of B redefines the property, replacing the one defined by A and losing the value created by A in the process. This behavior mirrors JavaScript's behavior as described above.

To resolve this issue, you can disable the setting to achieve the desired output from your code; playground link (note: other type errors have not been fixed). However, it is recommended to update your code instead. From a design perspective, A should not be initializing properties that it does not define. It is also not safe to assign all properties from an object to the instance being initialized.

One solution is to write constructors that explicitly copy the intended data. This approach ensures that instances do not inherit properties from source that are not meant for them, as shown in the following JavaScript example (TypeScript version here [again, other type errors remain]):

class A { // A: Model
    constructor(source){
        Object.keys(source)
        .forEach(key => {
            if(!this[key]){
                this[key] = source[key];
            }
        });
    }
}

class B extends A{ // B: User
    first_name;
}

let v = new B({first_name: "nof", shouldNotBeHere: "Hi there!"});
console.log(v);
// B { first_name: "nof", shouldNotBeHere: "Hi there!" }
//                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

If you prefer to have A perform the blind copy, you can eliminate the compiler error (though not the problem itself) by disabling the flag.

Answer №3

Could you please specify the data type of the "n1" attribute in class B by including a type declaration:

n1!: string;

The exclamation mark after the variable name signifies that it is a non-nullable property, guaranteeing that "n1" will constantly hold a value.

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

What is the process for moving the final character to the beginning of a string?

Initially, the last letter in the string is being displayed. How can I rearrange it so that the last character appears first in the value? https://i.stack.imgur.com/uGq6H.jpg contentHtml += "<td rowspan1=\"" + 1 + "\" class=\"" + ( ...

Encountering the "TypeError: Unable to access property 'indexOf' of undefined" error while utilizing the ipfs-api

During my development work with the ipfs-api, I ran into an issue where adding an image file to the ipfs node was not functioning properly. Upon further investigation into the error details, it appears that the protocol is being treated as undefined in the ...

Sharing and showcasing files directly from a local directory

Recently diving into NodeJS and web development, I've successfully used multer to upload a single file within my web application. The file gets uploaded to my "uploads" folder flawlessly, and now I'm planning on storing the file path in my databa ...

Passing a value from the Trigger button to the Modal button in Angular-UI Bootstrap

Seeking some help. I am working with angular-ui-bootstrap alongside php and mysql. My goal is to pass a value from a list of links (dynamically generated from php mysql) to a modal button each time the modal is loaded. HTML // The link below is generated ...

What is the method to link a progress bar to the value of a text input?

I'm currently working on an application where users need to input the percentage of their skill proficiency, and I want the progress bar to automatically reflect that value. I require assistance with this task, preferably using PHP only, but Java can ...

Angular Component - Array missing initial value in @Input property

Having trouble transferring values between components? I'm currently dealing with a situation involving two components: report-form and comment-form. The report form contains an array of comments, displaying a list of comments and a button for each on ...

What sets useSession, getSession, and getServerSession apart in NextAuth?

After searching for the answer on the query at this question, I am still not quite clear on the distinction. Additionally, a new method getServerSession() has been introduced. Can someone please provide further clarification on the variances between thes ...

When using Vue2, pushing a string to an array simply replaces the existing string instead of appending it

My current task involves manipulating a local data array by adding and removing strings within a method. However, I have noticed that my logic always results in the array containing only a single string passed to the updateIdArr method. Even after removin ...

JasmineJS: manipulating the DOM to achieve the desired outcome

Currently, I am in the process of writing unit tests for a function that requires fetching values from the DOM for processing. getProducts: function() { //Creating query data var queryData = {}; var location = this.$('#location').val(); ...

Verify whether a div element is styled in a specific manner

Upon initial load of my website, if the page is maximized or in fullscreen mode, the comBrand div will have specific CSS properties applied. However, during a resize event, I use the .css() function to adjust the properties of this element so it doesn&apos ...

Creating a system to add and limit dynamic fields with a counter in jQuery

Check out this fiddle link http://jsfiddle.net/gKJEs/80/ I'm looking for a way to limit the number of rows that can be added, let's say up to 5. Here is the HTML code: <table id="table"></table> <button id="addRowBtn">Add Ro ...

Trouble with rendering inline images from markdown files in GatsbyJS

I've been trying to include inline images in my markdown file with the gatsby-remark-images plugin. However, I'm facing an issue where the image is not loading on my local host. I'm not sure if it's a syntax error or if I'm missing ...

The styles from bootstrap.css are not displaying in the browser

Currently in the process of setting up my angular 2 project alongside gulp by following this helpful tutorial: I've added bootstrap to the package.json, but unfortunately, it's not reflecting in the browser. I can see it in the node_modules and ...

Encountering a problem with populating data in postgresql

After executing the npm run seed command to populate data into PostgreSQL, even though the seeding process seemed to be successful, I couldn't locate the seeded data in the PostgreSQL database. Can anyone advise on what might have gone wrong or sugges ...

The AJAX response is not functioning as expected

I've encountered an issue with my AJAX code for an online food store. Every time I run it, a pop-up message saying something went wrong appears instead of the expected output. I suspect there might be an error in either the connection handlers or the ...

Tips for handling notifications that have been read and unread in a React application

In my current project using React JS, I am tasked with creating a notifications component that will display account-related activities. The notifications need to be sorted into read and unread categories. My main question is how should I manage the read a ...

What is the best method to pass a JavaScript file array to a Node.js server?

Is it possible to transfer data from a Javascript file linked to an HTML page to a Node.js file on a post route without displaying it on the HTML page? If so, what is the best way to accomplish this? ...

Can anyone provide guidance on how to calculate the total sum of a JavaScript array within an asynchronous function?

Currently, I am working with Angularjs Protractor for end-to-end testing and faced an issue while trying to calculate the sum of values in a column. Although I am able to print out each value within the loop successfully, I am struggling to figure out ho ...

Struggling to get the hang of CSS animation?

Here is a code snippet that I am using: //Code for animating skills on view document.addEventListener("DOMContentLoaded", function(event) { function callback(observations, observer) { observations.forEach(observation => { if (observati ...

Building a custom search modal using RenderPartial in Yii

I'm currently working on developing a modal box that will enable users to filter and search through a grid. The main objective is to allow users to retrieve information from one database while simultaneously completing a form in another database. Alt ...