Skip to content

Error TS2729 should occur inside arrow function #61212

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

Closed
steffen-4s1 opened this issue Feb 18, 2025 · 2 comments
Closed

Error TS2729 should occur inside arrow function #61212

steffen-4s1 opened this issue Feb 18, 2025 · 2 comments

Comments

@steffen-4s1
Copy link

πŸ”Ž Search Terms

  • ts2729
  • used before its initialization
  • arrow function in fields
  • useDefineForClassFields

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about >= 5

⏯ Playground Link

https://www.typescriptlang.org/play/?useDefineForClassFields=true&target=11#code/MYGwhgzhAEBiD29oG8BQ1oAcCuAjEAlsNAGYECmIAJgILQC80A2gLoB0AtmJgBQ8CUDAHwp0GaABcAFgQhsI5AE4A3IuTZV4AsQF9+qMTnxFSFagCEGkmXIUq1GrfsN5CxYPAB2ECYuzAJeEUeTEUCZTAJcmg7VWByAC4UaE0kgWEY3wJPAHNoPRQdVB0gA

πŸ’» Code

class Foo {
  public fieldA = [].map(() => {
    // access service inside arrow function shouldn't be work with useDefineForClassFields = true
    this.service.do()
    //   ^^^^^^^ expected error ts(2729)
  })

  public fieldB = this.service.do()
  //                   ^^^^^^^ Property 'service' is used before its initialization. (ts(2729))

  public constructor(private service: { do: () => string }) {}
}

Just for sake of completeness:

JavaScript output with useDefineForClassFields = true
class Foo {
  service;

  fieldA = [].map(() => {
    this.service.do();
  });

  fieldB = this.service.do();

  constructor(service) {
    this.service = service;
  }
}
JavaScript output with useDefineForClassFields = false
class Foo {
  constructor(service) {
     this.service = service;

     this.fieldA = [].map(() => {
       this.service.do();
     });

     this.fieldB = this.service.do();
  }
}

πŸ™ Actual behavior

Error Property 'service' is used before its initialization.(2729) only occurs for fieldB initialization.

πŸ™‚ Expected behavior

Error Property 'service' is used before its initialization.(2729) should also occur for fieldA initialization inside the arrow function.

Additional information about the issue

With useDefineForClassFields = true (which is the default) the generated JavaScript code in my example won't work, because service is accessed even though it is still undefined.

If I set the setting to false, as is done automatically for earlier targets, everything works. However, I would like to avoid using the old format for classes.

@MartinJohns
Copy link
Contributor

This is working as intended. The compiler doesn't know when your arrow function is invoked, and it's a reasonable assumption it will be invoked after your variable is set.

This would be improved with #58729, allowing the compiler to know that the arrow function passed to Array.map() will be invoked immediately.

@steffen-4s1
Copy link
Author

Thank you for your feedback and clarification.

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

No branches or pull requests

2 participants