-
Notifications
You must be signed in to change notification settings - Fork 47.7k
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
feat(eslint-plugin-react-hooks): convert to typescript and package type declarations #32240
feat(eslint-plugin-react-hooks): convert to typescript and package type declarations #32240
Conversation
Core migration is done. Tests are green when run locally. Now working on integrating it into the existing build infra and developing e2e test fixtures. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on this! I think as it is the PR is bordering on being way too large to review thoroughly. It'd be good if we can split this up into a few smaller PRs. For example the peripheral changes (installing/updating packages) or script/babel/build changes could also be split.
I would also recommend not rewriting existing patterns like for loops to for..of
and x == null
to !x
, since they have subtle differences. Keep the conversion as 1:1 as possible unless it's strictly necessary for type soundness. Additionally if you need to add new code (eg adding continue
inside of a loop), could you add more context on why it's necessary?
packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js
Outdated
Show resolved
Hide resolved
if (!referenceNode) { | ||
continue; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fastFindReferenceWithParent
returns null if it's unable to find a suitable node, but all the logic below this assumes that it's returned a Node. In practice, it shouldn't really ever not return a node, so this is more of an edge case, but since the function isn't narrowing out null, this early return keeps the rest of the assumptions in tact.
This comment was marked as off-topic.
This comment was marked as off-topic.
@poteto thanks for taking a look at this already! I've made some updates and responded to several of the feedback items.
I'm thinking these could be good candidates for breaking out as separate changes, but wanted to get your input:
Thoughts? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for addressing the previous feedback!
That split makes sense. I would also try to get the build changes done in an earlier PR, and this PR could be for just the changes to the rules themselves. |
Sounds good. I updated the description of this PR to include tasks for each of those, and will link PRs as I work through each. |
…useEffectEvent Contributing to facebook#32240, this change removes the experimental `useEffectEvent` checks in the two react hooks eslint rule. As the api is refined, and the compiler rule(s) are incorporated into this plugin, these checks will be covered then.
…useEffectEvent Contributing to facebook#32240, this change removes the experimental `useEffectEvent` checks in the two react hooks eslint rule. As the api is refined, and the compiler rule(s) are incorporated into this plugin, these checks will be covered then.
…useEffectEvent Contributing to facebook#32240, this change removes the experimental `useEffectEvent` checks in the two react hooks eslint rule. As the api is refined, and the compiler rule(s) are incorporated into this plugin, these checks will be covered then.
…useEffectEvent Contributing to facebook#32240, this change removes the experimental `useEffectEvent` checks in the two react hooks eslint rule. As the api is refined, and the compiler rule(s) are incorporated into this plugin, these checks will be covered then.
… migration Contributing to facebook#32240, this change adds the dev dependencies needed to support the migration of the plugin to typescript.
… migration Contributing to facebook#32240, this change adds the dev dependencies needed to support the migration of the plugin to typescript.
… migration Contributing to facebook#32240, this change adds the dev dependencies needed to support the migration of the plugin to typescript.
… migration (#32279) <!-- Thanks for submitting a pull request! We appreciate you spending the time to work on these changes. Please provide enough information so that others can review your pull request. The three fields below are mandatory. Before submitting a pull request, please make sure the following is done: 1. Fork [the repository](https://github.com/facebook/react) and create your branch from `main`. 2. Run `yarn` in the repository root. 3. If you've fixed a bug or added code that should be tested, add tests! 4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch TestName` is helpful in development. 5. Run `yarn test --prod` to test in the production environment. It supports the same options as `yarn test`. 6. If you need a debugger, run `yarn test --debug --watch TestName`, open `chrome://inspect`, and press "Inspect". 7. Format your code with [prettier](https://github.com/prettier/prettier) (`yarn prettier`). 8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only check changed files. 9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`). 10. If you haven't already, complete the CLA. Learn more about contributing: https://reactjs.org/docs/how-to-contribute.html --> ## Summary Contributing to #32240, this change adds the dev dependencies needed to support the migration of the plugin to typescript.
Contributing to facebook#32240, this change adds the tsconfig, tsup config, and estree type declarations that will be needed for that plugin's typescript migration.
Contributing to facebook#32240, this change adds the tsconfig, tsup config, and estree type declarations that will be needed for that plugin's typescript migration.
<!-- Thanks for submitting a pull request! We appreciate you spending the time to work on these changes. Please provide enough information so that others can review your pull request. The three fields below are mandatory. Before submitting a pull request, please make sure the following is done: 1. Fork [the repository](https://github.com/facebook/react) and create your branch from `main`. 2. Run `yarn` in the repository root. 3. If you've fixed a bug or added code that should be tested, add tests! 4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch TestName` is helpful in development. 5. Run `yarn test --prod` to test in the production environment. It supports the same options as `yarn test`. 6. If you need a debugger, run `yarn test --debug --watch TestName`, open `chrome://inspect`, and press "Inspect". 7. Format your code with [prettier](https://github.com/prettier/prettier) (`yarn prettier`). 8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only check changed files. 9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`). 10. If you haven't already, complete the CLA. Learn more about contributing: https://reactjs.org/docs/how-to-contribute.html --> ## Summary Contributing to #32240, this change adds the tsconfig, tsup config, and estree type declarations that will be needed for that plugin's typescript migration.
10ad067
to
ede1e95
Compare
I've rebased following the other PRs merging, and resolved merge conflicts. I'll tackle the build changes next. First in this branch, since I have something to work against, and then break it out into a separate change to review on its own. |
b84fdfa
to
39a6137
Compare
I isolated this mv into its own PR to ensure we're able to maintain commit history for these files.
…pe declarations This change converts the eslint hooks plugin to typescript, which also allows us to include type declarations in the package, for those using [typescript eslint configs](https://eslint.org/blog/2025/01/eslint-v9.18.0-released/#stable-typescript-configuration-file-support).
…pe declarations This change converts the eslint hooks plugin to typescript, which also allows us to include type declarations in the package, for those using [typescript eslint configs](https://eslint.org/blog/2025/01/eslint-v9.18.0-released/#stable-typescript-configuration-file-support).
…pe declarations This change converts the eslint hooks plugin to typescript, which also allows us to include type declarations in the package, for those using [typescript eslint configs](https://eslint.org/blog/2025/01/eslint-v9.18.0-released/#stable-typescript-configuration-file-support).
This change updates the build script to support packages containing typescript source. I added a new `tsconfig` bundle property to use for detecting typescript js bundle types. When a bundle has `tsconfig` it will use the `@rollup/typescript` plugin instead of the flow plugin, in the plugin stack. Additionally, I added two new bundle types for DTS bundles (CJS_DTS and ESM_DTS). This is for generating .d.ts bundles. For dts only bundles, we only need to use the dts rollup plugin. The rest of the bundle creation logic should hold.
Now that eslint-plugin-react-hooks is written in typescript, we need a pre-step in jest to build the plugin prior to running tests. It's a bit unfortunate that there are effectively 2 build setups for the eslint plugin: one from rollup as part of the main React build, and a standalone tsup (esbuild) step for tests. We should unify these in a follow up PR.
….ts file This change adjusts the package.json for the eslint-plugin-react-hooks to point at the product of the root level build, instead of the temporary tsup package-level build. It also adds an `index.d.ts` to the `npm` folder that's copied to the root of the package after build. Lastly, by adding a `name` property to the bundle definition, it emits the same file names as it did before changing the `target`. As a result of these changes, we don't need to do the additional jest global set up. I'd like to follow this up with a little more setup at the package level to allow for faster local devloop, but that's not critical for this change to land.
This change adds tsup back for package-level testing. I'll iterate on this to see if we can drop this in a follow-up change
This change removes tsup from the devloop of `eslint-plugin-react-hooks`. I was originally using it to quickly run tests and builds as I was doing the migration, but now that we've added support to the larger rollup build process, there's no longer a need for it. I've added an index.js to the root of the package folder that's just a proxy for the `src/index.ts`. It uses tsx to load it for other consumers in the monorepo (e.g. the eventual e2e tests fixtures). For jest, the index.js is able to load the ts file due to the added configuration in the package's babel and jest configs. This `index.js` will only be used for dev purposes. The `index.js` that's in the `npm` folder is what will actually make it into the published package.
39a6137
to
bddfebf
Compare
Now that we've knocked out and merged all of the prereqs, and I tested everything against the new test fixtures from #32396, this should be ready for review 😊 After this merges I'll update the v9 test fixture to use a ts-based config and add the fixture tests to CI for future validation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for all the work getting this ready!
|
||
function last(array) { | ||
return array[array.length - 1]; | ||
function last<T>(array: T[]): T { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is super minor but could you use the Array<T>
syntax instead for arrays? It's a convention we also use for the compiler, as our team finds them easier to scan.
@@ -140,6 +183,9 @@ export default { | |||
|
|||
// Get the current scope. | |||
const scope = scopeManager.acquire(node); | |||
if (!scope) { | |||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe throw here if we didn't find a scope?
let declaration = def.node.parent; | ||
if (declaration == null) { | ||
let declaration = defNode.parent; | ||
if (declaration == null && componentScope) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we use a specific comparison here?
@@ -219,6 +266,8 @@ export default { | |||
} | |||
} | |||
if ( | |||
declaration && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here too
Feel free to address the other comments in a follow up PR, I'm going to merge this for now. |
…pe declarations (#32240) <!-- Thanks for submitting a pull request! We appreciate you spending the time to work on these changes. Please provide enough information so that others can review your pull request. The three fields below are mandatory. Before submitting a pull request, please make sure the following is done: 1. Fork [the repository](https://github.com/facebook/react) and create your branch from `main`. 2. Run `yarn` in the repository root. 3. If you've fixed a bug or added code that should be tested, add tests! 4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch TestName` is helpful in development. 5. Run `yarn test --prod` to test in the production environment. It supports the same options as `yarn test`. 6. If you need a debugger, run `yarn test --debug --watch TestName`, open `chrome://inspect`, and press "Inspect". 7. Format your code with [prettier](https://github.com/prettier/prettier) (`yarn prettier`). 8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only check changed files. 9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`). 10. If you haven't already, complete the CLA. Learn more about contributing: https://reactjs.org/docs/how-to-contribute.html --> ## Summary This change converts the eslint hooks plugin to typescript, which also allows us to include type declarations in the package, for those using [typescript eslint configs](https://eslint.org/blog/2025/01/eslint-v9.18.0-released/#stable-typescript-configuration-file-support). ### Constituent changes that should land before this one - [x] ~#32276 - [x] #32279 - [x] #32283 - [x] #32393 - [x] #32396 Closes #30119 --------- Co-authored-by: Lauren Tan <poteto@users.noreply.github.com> DiffTrain build for [5adf402](5adf402)
This change addresses several feedback items from facebook#32240
This change addresses several feedback items from facebook#32240
…nditionals (#32400) - [build(eslint-plugin-react-hooks): add ts-linting](4c0fbe7) This change adds configuration to the eslint config governing `eslint-plugin-react-hooks` to use the typescript-eslint plugin and parser. It adds the typescript-recommended config, and configures the team's preferred `array-type` convention. - [refactor(eslint-plugin-react-hooks): improve conditionals](540d0d9) This change addresses several feedback items from #32240 - [ci (eslint-e2e): exclude nested node_modules from cache](a3279f4) This change removes the nested fixture `node_modules` from being cached, so that the symbolic link can be made after the build happens.
…nditionals (#32400) - [build(eslint-plugin-react-hooks): add ts-linting](4c0fbe7) This change adds configuration to the eslint config governing `eslint-plugin-react-hooks` to use the typescript-eslint plugin and parser. It adds the typescript-recommended config, and configures the team's preferred `array-type` convention. - [refactor(eslint-plugin-react-hooks): improve conditionals](540d0d9) This change addresses several feedback items from #32240 - [ci (eslint-e2e): exclude nested node_modules from cache](a3279f4) This change removes the nested fixture `node_modules` from being cached, so that the symbolic link can be made after the build happens. DiffTrain build for [4632e36](4632e36)
Summary
This change converts the eslint hooks plugin to typescript, which also allows us to include type declarations in the package, for those using typescript eslint configs.
Constituent changes that should land before this one
fix(eslint-plugin-react-hooks): remove experimental checks involving useEffectEvent #32276Closes #30119