assemblyscript
assemblyscript copied to clipboard
Regression: ERROR TS2564: Property 'module/A#c' has no initializer and is not assigned in the constructor before 'this' is used or returned.
Link: here
Minimal reproduction: (as far as I can reduce it)
class B {}
class A {
b: B;
c: B;
constructor() {
// this should be safe?
this.b = new B();
this.c = this.b;
}
}
export function fib(n: i32): i32 {
let a = new A();
return 0;
}
Error:
;; ERROR TS2564: Property 'module/A#c' has no initializer and is not assigned in the constructor before 'this' is used or returned.
;; :
;; 4 │ c: B;
;; │ ~
;; └─ in module.ts(4,3)
;; :
;; 7 │ this.c = this.b;
;; │ ~~~~~~
;; └─ in module.ts(7,14)
This is in fact a relatively strict check atm, but it is intended. Imagine that this.b is a property that executes arbitrary code (accessing this) when accessed, then in that code this.c has not yet been assigned.
Edit: Makes me realize that this.b = ... before is similar, but doesn't diagnose an error. I guess what we need there is to detect if something is an actual getter or setter, and only then diagnose 🤔
I was tracking this bug for some time and realized it is actually a feature #1349. In brief, the compiler checks if the class is fully initialized before handling a call on this in the constructor. It is indeed a different behavior than Typescript (so a bit confusing), but as mentioned in the above PR, it can be overcome with an assertion.
class B {}
class A {
b: B;
c!: B; // add assertion
constructor() {
this.b = new B();
this.c = this.b;
}
}
/** Calculates the n-th Fibonacci number. */
export function fib(n: i32): i32 {
let a = new A();
return 0;
}
This compiles just fine.
A smarter way to handle this is to only check the accessed properties rather than all properties on this. What do you think?