Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(eslint-plugin-react-hooks): convert to typescript and package ty…
Browse files Browse the repository at this point in the history
…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).
michaelfaith committed Jan 29, 2025
1 parent 4b38c7c commit 10ad067
Showing 2 changed files with 17 additions and 15 deletions.
18 changes: 9 additions & 9 deletions packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.ts
Original file line number Diff line number Diff line change
@@ -237,7 +237,7 @@ const rule = {
return false;
}
const def = resolved.defs[0];
if (!def) {
if (def == null) {
return false;
}
// Look for `let stuff = ...`
@@ -246,7 +246,7 @@ const rule = {
return false;
}
let init = defNode.init;
if (!init) {
if (init == null) {
return false;
}
while (init.type === 'TSAsExpression' || init.type === 'AsExpression') {
@@ -255,13 +255,13 @@ const rule = {
// Detect primitive constants
// const foo = 42
let declaration = defNode.parent;
if (!declaration && componentScope) {
if (declaration == null && componentScope) {
// This might happen if variable is declared after the callback.
// In that case ESLint won't set up .parent refs.
// So we'll set them up manually.
fastFindReferenceWithParent(componentScope.block, def.node.id);
declaration = def.node.parent;
if (!declaration) {
if (declaration == null) {
return false;
}
}
@@ -406,13 +406,13 @@ const rule = {
break;
}
}
if (!fnScope) {
if (fnScope == null) {
return false;
}
// Does this function capture any values
// that are in pure scopes (aka render)?
for (const ref of fnScope.through) {
if (!ref.resolved) {
if (ref.resolved == null) {
continue;
}
if (
@@ -488,7 +488,7 @@ const rule = {
node,
reference.identifier,
);
if (!referenceNode) {
if (referenceNode == null) {
continue;
}
const dependencyNode = getDependency(referenceNode);
@@ -525,7 +525,7 @@ const rule = {
}

const def = reference.resolved.defs[0];
if (!def) {
if (def == null) {
continue;
}
// Ignore references to the function itself as it's not defined yet.
@@ -1707,7 +1707,7 @@ function scanForConstructions({
const constructions = declaredDependencies
.map(({key}) => {
const ref = componentScope.variables.find(v => v.name === key);
if (!ref) {
if (ref == null) {
return null;
}

14 changes: 8 additions & 6 deletions packages/eslint-plugin-react-hooks/src/index.ts
Original file line number Diff line number Diff line change
@@ -8,8 +8,6 @@ import RulesOfHooks from './RulesOfHooks';
import ExhaustiveDeps from './ExhaustiveDeps';
import type {ESLint, Linter, Rule} from 'eslint';

const packageJson: {name: string; version: string} = require('../package.json');

// All rules
const rules = {
'rules-of-hooks': RulesOfHooks,
@@ -30,7 +28,9 @@ const legacyRecommendedConfig = {

// Plugin object
const plugin = {
meta: {name: packageJson.name, version: packageJson.version},
// TODO: Make this more dynamic to populate version from package.json.
// This can be done by injecting at build time, since importing the package.json isn't an option in Meta
meta: {name: 'eslint-plugin-react-hooks'},
rules,
configs: {
/** Legacy recommended config, to be used with rc-based configurations */
@@ -55,8 +55,10 @@ const plugin = {
},
} satisfies ESLint.Plugin;

// These exports are for backwards compatibility with eslint versions before v9
const configs = plugin.configs;
export {configs, rules};
const meta = plugin.meta;
export {configs, meta, rules};

export default plugin;
// TODO: If the plugin is ever updated to be pure ESM and drops support for rc-based configs, then it should be exporting the plugin as default
// instead of individual named exports.
// export default plugin;

0 comments on commit 10ad067

Please sign in to comment.