Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Regression: ERROR TS2564: Property 'module/A#c' has no initializer and is not assigned in the constructor before 'this' is used or returned. #2576

Open
jtenner opened this issue Nov 22, 2022 · 2 comments
Labels

Comments

@jtenner
Copy link
Contributor

jtenner commented Nov 22, 2022

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)
@dcodeIO
Copy link
Member

dcodeIO commented Nov 23, 2022

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 🤔

@dcodeIO dcodeIO added the bug label Nov 23, 2022
@ppppqp
Copy link

ppppqp commented Jan 28, 2023

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants