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

What is the best way to retrieve HTML content using an Angular method?

Okay, so the title might not be the greatest...but I couldn't think of anything better: I want to emphasize search keywords in the result list...that's why I'm having trouble with this problem. CSS: .highlightText{ font-weight: bold; } In ...

A guide on loading modules dynamically using React and Typescript from a server

I am working on a React / Typescript / Webpack / React-Router application that contains some large JS modules. Currently, I have two bundles (common.js and app.js) included on every page, with common.js being a CommonsChunkPlugin bundle. However, there is ...

Incorrect Angular Routing Component OpeningI am experiencing an issue where

I am facing an issue with lazy loading a module, where it is not correctly displaying the desired component. Even though the route seems correct, it shows a different component instead. Despite specifying the path for "Push-Campaign", it displays the "Cli ...

What is the best way to implement persistStore in Redux-Toolkit?

Here is my setup: import AsyncStorage from '@react-native-async-storage/async-storage' import { persistStore, persistReducer } from 'redux-persist'; import { configureStore } from "@reduxjs/toolkit"; import { searchReducer } f ...

Transforming the data type of a variable

Recently, I decided to switch my file name from index.js to index.ts. Here's an example of the issue I'm facing: let response = "none" let condition = true if(condition){ response = {id: 123 , data: []} } console.log(response) Howev ...

Having trouble setting a default value for your Angular dropdown? Looking for alternative solutions that actually work?

Objective: Customize the default value for a dropdown menu to switch between English (/en/) and Spanish (/es/) addresses on the website. Challenge: Despite extensive research, including consulting various sources like Angular 2 Dropdown Options Default Va ...

RxJs: Generating an observable based on changes in a field's value

Is there a way to generate an Observable using the variable this.pending as its source? I'm looking to create an Observable that will produce a new feed each time the value of this.pending changes. For example, if I update this.pending to be false i ...

How to retrieve the type of a computed keyof T as a generic type within TypeScript

I am working with two different interfaces: interface PersonRequirements{ user:string, password:string, id:number } export interface Requirement<R> { name: keyof R & string, save: () => any,/* I want this return type to be ...

Adding an additional element to an object - crossroads of combining types versus sequential examination

Here's a query for you: AppendToObject. When I first tackled this question, my initial instinct was to utilize type intersection like so: type AppendToObject<T, U extends PropertyKey, V> = T & {[P in U]: V} Unfortunately, this solution did ...

What is the process for defining a global variable within a module in Typescript?

I've already included a global value in my global JavaScript context: const fs = require('fs') For a specific reason, I need to include it in the global scope. Now, I want to create a .d.ts file to declare the global variable with a stron ...

Issue with Angular 17 button click functionality not functioning as expected

Having trouble with a button that should trigger the function fun(). Here's the code snippet I'm using. In my TS file: fun(): void { this.test = 'You are my hero!'; alert('hello') } Here is the respective HTML: &l ...

What is the best way to include an item in a list with a specific identifier using the useState Record data type in a React application built with TypeScript?

Here is the structure of my Record type: const PEOPLE_MAP_INIT: Record<string, Person[]> = { "1": [], "2": [], "3": [] }; I have initialized the useState like this: const [PEOPLE_MAP, SET_PEO ...

Navigating through different components within a single page

Each segment of my webpage is a distinct component, arranged consecutively while scrolling e.g.: <sectionA></sectionA> <sectionB></sectionB> <sectionC></sectionC> All the examples I've come across involve creating ...

Error: Uncaught TypeError - Unable to access 'reduce' property of undefined value

Currently, I am focusing on implementing yup validation. Specifically for FileList validation, encountering an issue where leaving the input empty triggers the following error message: enter image description here Below is the code snippet in question: (C ...

Tips for implementing a reusable instance of a class in (SSR) React (comparable to a @Bean in Spring)

I am currently developing a new application using Next.js and React (Server Components) in TypeScript. In order to showcase and evaluate the app, I need to support two different data sources that provide identical data through separate APIs. My goal is to ...

Encountering an error in Cytoscape using Angular and Typescript: TS2305 - Module lacks default export

I am working on an Angular app and trying to integrate Cytoscape. I have installed Cystoscape and Types/cytoscape using npm, but I encountered an error when trying to import it into my project. To troubleshoot, I started a new test project before implement ...

404 Error: Unable to Locate Socket Io

I'm currently working on implementing a chat feature in Angular 2 using Socket IO, following this tutorial. However, I encountered an error message during a test on the server: GET http://localhost:3000/socket.io/?EIO=3&transport=polling& ...

What is the most effective way to move specific data from one page to another in Angular/Typescript?

Welcome to my Main Page! https://i.stack.imgur.com/m9ASF.png This is where I want to start my journey. https://i.stack.imgur.com/E8pAW.png My goal is to click the Last 1 Day button to redirect to another page with the date filter and ItemId values already ...

Achieve validation of numerous variables without the need for a string of if-else

If we have three variables, such as firstName, lastName, and email, how can we check if they are empty or not without using multiple if else blocks? let firstName = "John"; let lastName = "Doe"; let email = "john.doe@example.com"; if (firstName.trim() == ...

How to remove a specific type from a generic type in Typescript without using Exclude<>?

I am looking for a solution to prevent my function from working with Moment objects when storing values in local storage. Currently, the function dynamically stringifies and stores values, but I want to exclude Moment objects from being processed. Here is ...