The initial values of Typescript class members are merged directly into the class constructor

This issue has been well documented (check out Initializing variables inline during declaration vs in the constructor in Angular with TS on SO for reference), but it can lead to challenging memory problems.

Take a look at the example below

class Bar {
    private num: number;
    private closure: any;
  constructor(num: number, closure : any) {
    this.num = num;
    this.closure = closure;
}
}

class Foo {
  private bar = new Bar(5, (a: number, b: number) => {return a < b;});
  private baz: number;
  constructor(very_expensive_thing: any) {
    this.baz = very_expensive_thing.small_thing;
  }
}

If we were dealing with plain old javascript, there wouldn't be an issue as the Bar initializer wouldn't have access to the very_expensive_thing object.

However, typescript integrates the initialization of Bar into the constructor, causing it to retain the very_expensive_thing as seen in the generated javascript from the typescript playground v5.1.3:

"use strict";
class Bar {
    constructor(num, closure) {
        this.num = num;
        this.closure = closure;
    }
}
class Foo {
    constructor(very_expensive_thing) {
        this.bar = new Bar(5, (a, b) => { return a < b; });
        this.baz = very_expensive_thing.small_thing;
    }
}

The retention of a constructor parameter within the closure is not intuitive and doesn't follow standard scoping rules.

Although the solution is simple (move the closure outside of the class), feedback from experienced typescript users would be valuable in determining if this is a common pitfall or an actual issue. Is there a way to disable this inlining behavior to avoid such situations?

Answer №1

Class fields were officially added to JavaScript in ES2022. When configuring TypeScript to target a version of the JS runtime before ES2022, the code will be adjusted to work with that version by integrating the fields into the constructor. However, not all language features are downleveled in order to preserve every nuance, as seen in issues like microsoft/TypeScript#32743.

To maintain semantics close to JavaScript class fields, it is recommended to target ES2022 or later and enable the --useDefineForClassFields compiler option. This ensures that the output JavaScript closely resembles the TypeScript code without additional annotations or type modifiers:

class Foo {
    bar = new Bar(5, (a, b) => { return a < b; });
    baz;
    constructor(very_expensive_thing) {
        this.baz = very_expensive_thing.small_thing;
    }
}

Playground link to code

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

Using TypeScript to pass a callback function to labelFormatter in the legend of a Highcharts chart

I am currently experimenting with integrating HighCharts into an Angular2 project using TypeScript. My goal is to customize the appearance of the legend text, adding an image next to it. I've found that HighCharts provides a labelFormatter property w ...

Transporting a Typescript file to the customer using JavaScript

As a newcomer to typescript and in the process of creating a small application in visual studio 2013, I have noticed that when viewing the project in Chrome's developer tools, typescript files (*.ts) are being downloaded to the client. This could pote ...

Encountering issues while attempting to upload items to AWS S3 bucket through NodeJS, receiving an Access Denied error 403

I encountered an issue while attempting to upload objects into AWS S3 using a NodeJS program. 2020-07-24T15:04:45.744Z 91aaad14-c00a-12c4-89f6-4c59fee047a1 INFO uploading to S3 2020-07-24T15:04:47.383Z 91aaad14-c00a-12c4-89f6-4c59fee047a1 IN ...

Using Typescript/JSX to assign a class instance by reference

Looking to access an object's property by reference? See the code snippet below; class Point{ x:number; y:number; constructor(x,y) { this.x=x; this.y=y; } } const a = { first: new Point(8,9), second: new Point(10,12) }; let someBoo ...

Several values are not equal to the typeorem parameter

I am looking for a way to create a Typeorm query that will return results similar to the following SQL statement: SELECT * FROM Users WHERE id <> 3 and id <> 8 and id <> 23; Any suggestions on how I can achieve this? Thank you! ...

Utilizing Angular's async pipe to dynamically customize and assign values to variables

I have a parent component named A with over 20 child components, all of which extend A and are located within <ng-content></ng-content>. Within component A, I am updating the value of the showContent variable in multiple places. The issue aris ...

Identifying one of the two possible return types automatically

In my code, there is a function named isDone() that will return data from either an array of hashes or a dictionary of hashes: public async isDone() { this.startDelayedTasks(); await Promise.all(this._tasks); const hadErrors = this._failed.length &g ...

Convert a regular element into a DebugElement within an Angular framework

Recently, I was working on testing an Angular Component which was going smoothly until I encountered a challenging issue that has been perplexing me for days. My main objective was to test whether the method "ajouterCompteurALaCampagne" is being called whe ...

Challenges with utilizing Ionic Native in a cross-platform application

I am currently developing an application using Ionic 2 that can function both as a website in a browser and as a mobile app on iOS and Android. One key aspect of the app is its use of the SQLite plugin when accessed on mobile devices. However, I have encou ...

What are the steps to access a query parameter within an API route.js file using the latest App routing strategy?

Here is the goal I am aiming for: Utilize Next.js with App router. Establish a backend route /api/prompt?search=[search_text] Retrieve and interpret the search query parameter in my route.ts file. Based on the search parameter, send back data to the front ...

TSX: Interface Definition for Nested Recursive Array of Objects

I'm having trouble making my typescript interface compatible with a react tsx component. I have an array of objects with possible sub items that I need to work with. Despite trying various interfaces, I always run into some kind of error. At the mome ...

Creating an RxJS observable stream from an event emitted by a child element in an Angular 2 component template

Currently incorporating Angular 2.0.0-rc.4 alongside RxJS 5.0.0-beta.6. In the midst of exploring various methods for generating observable streams from events, I find myself inundated with choices and would like to gather opinions. Recognizing that there ...

Unexpected errors are encountered when using ng serve

When I run the ng serve command, unexpected errors are occurring on my system. The errors include: PS C:\Users\SAYED-SADAT\Desktop\data\coding\itsm-frontend\itsm-frontend> ng serveYour global Angular CLI version (13.0 ...

Ways to package object fields within an array

I am in possession of an object with various properties, ranging from arrays to objects. My goal is to transform the object so that each sub field is encapsulated within an array. For instance: "head": { "text": "Main title", "su ...

InvalidTypeException: The properties accessed are undefined

Working with Angular 12 and encountering an error when trying to invoke a method within another method. Here is a simplified representation of my situation (in TypeScript, specifically for Angular: export class SomeClass { testvariable on ...

Issue with Ant Design form validation

After reading through the documentation, I attempted to implement the code provided: Here is a basic example: import { Button, Form, Input } from "antd"; export default function App() { const [form] = Form.useForm(); return ( <Form f ...

Tips for setting up a hierarchical mat-table within a parent table that supports expandable rows using Angular Material

Here is the data that I am working with: [ { "_id": "c9d5ab1a", "subdomain": "wing", "domain": "aircraft", "part_id": "c9d5ab1a", "info.mimetype": "application/json", "info.dependent": "parent", ...

Hold off on addressing the nested loops within a TypeScript subscription

Goal: Ensure all nested loops complete processing before returning final value. Problem: Final value returned prematurely, before completion of loop processing. In the code snippet below, I am sending paramListToComplete to a data service for creating a ...

Can an excessive amount of classes cause my Angular application to run sluggishly?

Within my Angular 7 application, I have generated approximately 200 to 300 classes for model types (e.g. component.model.ts) solely for type checking purposes. I have not instantiated any objects from these classes. As I navigate through the application, ...

The typescript MenuProvider for react-native-popup-menu offers a range of IntrinsicAttributes

Looking to implement drop-down options within a Flatlist component, I've utilized the React Native Popup Menu and declared MenuProvider as the entry point in App.tsx. Encountering the following error: Error: Type '{ children: Element[]; }' ...