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

ts-migrate adding setState: any type declaration to react component classes, causing compilation problem #100

Open
2c2c opened this issue Feb 21, 2021 · 3 comments
Labels
bug Something isn't working

Comments

@2c2c
Copy link

2c2c commented Feb 21, 2021

After a ts-migrate on my project, I observed react classes with setState: any would compile to have this.setState = void 0; in their constructor, leaving you with "TypeError: this.setState is not a function` errors

@edsrzf
Copy link
Collaborator

edsrzf commented Apr 26, 2021

It looks like this can happen if the React types package (@types/react) is not installed when the migration runs. In this case, ts-migrate cannot tell that setState comes from the base class, so the declare-missing-class-properties plugin adds a declaration.

It might be nice if ts-migrate could install @types packages for dependencies that don't have their own types, prior to running any other migration.

I'm surprised that this.setState = void 0; is included in the compiled output, though. Could you please share what your compilation process is? Do you compile TypeScript using the TypeScript compiler or Babel, and what version do you use? I have tried some simple cases with both the TypeScript playground and Babel repl, but I can't convince either of them to emit this.setState = undefined; or this.setState = void 0; by including setState: any as a class member.

I wonder if classes that inherit from a base class with unknown types should use ! in their type declarations to assert that the property is initialized. Possibly that would prevent this initialization? I need to be able to reproduce the problem first though.

@2c2c
Copy link
Author

2c2c commented Apr 30, 2021

this was on a ~50 or so component project using create-react-app originally targetting js . a lot has moved in the month so not sure if I can give accurate repro steps unfortunately

in particular i cant remember if i went through the ts-migrate process before rerunning create-react-app and targetting typescript

@edsrzf
Copy link
Collaborator

edsrzf commented May 1, 2021

Thanks, I think I have an idea of what could cause this issue.

If you specify useDefineForClassFields in tsconfig.json, then the compiler will define each property using Object.defineProperty, which initializes it to undefined. (Example) I still can't convince the Babel repl to do it, but I'm sure there's some way as I believe that the TC39 proposal basically requires it.

It looks like even including ! does not change the way TypeScript emits the code.

The only kinda decent fix for this that I can see is adding an index signature when we encounter this case:

class Component extends React.Component {
  [k: string]: any;

  // ...
}

In the above case it's pretty avoidable if you install @types/react, but there may not always be types available.

@Rudeg Rudeg added the bug Something isn't working label Sep 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants