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?