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

[eslint-plugin-react-hooks] Missing type declarations #30119

Open
JstnMcBrd opened this issue Jun 27, 2024 · 12 comments · May be fixed by #32240
Open

[eslint-plugin-react-hooks] Missing type declarations #30119

JstnMcBrd opened this issue Jun 27, 2024 · 12 comments · May be fixed by #32240
Labels
Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug

Comments

@JstnMcBrd
Copy link

Versions: all

Severity: low

What

When imported in a TypeScript environment, eslint-plugin-react-hooks throws a "missing type declarations" error.

image

Why

This is because eslint-plugin-react-hooks does not have any type declarations bundled in the package. These would usually be in an index.d.ts file.

Also, eslint-plugin-react-hooks does not have a corresponding @types/... package in the DefinitelyTyped project for users to rely on.

Workaround

Users can follow the instructions in the error message and make a temporary module augmentation to declare their own types for the package.

In my personal project, I've done it this way:

// ./src/@types/eslint-plugin-react-hooks.d.ts
declare module 'eslint-plugin-react-hooks' {
	import type { ESLint } from 'eslint';
	const plugin: Omit<ESLint.Plugin, 'configs'> & {
		// eslint-plugin-react-hooks does not use FlatConfig yet
		configs: Record<string, ESLint.ConfigData>;
	};
	export default plugin;
}

But this will not automatically stay up-to-date with the package and is not guaranteed to be correct. Is it also incomplete and does not contain detailed information about the different configs in the plugin.

How to fix

There are several ways.

  1. Usually the preferred solution is just to write everything in TypeScript and let it auto-generate declaration files for you. But I understand if a complete rewrite is not on the table :)

  2. You could add a @types/eslint-plugin-react-hooks package in the DefinitelyTyped repo. But then your types would be defined in a completely different place from your actual code, and if you ever decide to migrate to TypeScript in the future, the old @types/... package would need to be deprecated. Sounds messy.

  3. Best solution, in my opinion. Just add a index.d.ts file to the package that declare the type exports of the package. Then define it as the type declarations in package.json. Easy peasy.

// package.json
+  "main": "index.js",
+  "types": "index.d.ts",
  "files": [
    "LICENSE",
    "README.md",
    "index.js",
+    "index.d.ts",
    "cjs"
  ],

I would be happy to do this myself. I just wanted to submit an issue first to confirm that the maintainers would approve.

Steps To Reproduce

  1. Install typescript, eslint-plugin-react-hooks
  2. Create a .ts file
  3. Import eslint-plugin-react-hooks

Code example

package.json

{
  "scripts": {
    "build": "tsc"
  },
  "dependencies": {
    "eslint-plugin-react-hooks": "^4.6.2"
  },
  "devDependencies": {
    "typescript": "^5.5.2"
  }
}

index.ts

import reactHooksPlugin from 'eslint-plugin-react-hooks';

(You'll need a tsconfig.json file too, but the settings are irrelevant to this example)

The current behavior

TypeScript build error.

The expected behavior

No errors.

@JstnMcBrd JstnMcBrd added the Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug label Jun 27, 2024
@JstnMcBrd
Copy link
Author

After trying to add a index.d.ts declaration file myself, I quickly realized I do not understand the build/bundling system for this monorepo. The declaration files were excluded from the build output.

I found the two different TODO comments explaining how the current build process isn't great for an eslint plugin.

./packages/eslint-plugin-react-hooks/npm/index.js

// TODO: this doesn't make sense for an ESLint rule.
// We need to fix our build process to not create bundles for "raw" packages like this.

./scripts/rollup/bundles.js

// TODO: it's awkward to create a bundle for this but if we don't, the package
// won't get copied. We also can't create just DEV bundle because it contains a
// NODE_ENV check inside. We should probably tweak our build process to allow
// "raw" packages that don't get bundled.

Fixing this would also allow adding declaration files to the published package, instead of being ignored by the bundler.

Makes me wonder if eslint-plugin-react-hooks should be in its own repository like most standalone npm packages, to avoid the awkwardness of a monorepo bundling system that wasn't designed for it. But I'll leave that decision to the maintainers.

@JstnMcBrd
Copy link
Author

Figured I'd dump the declaration files I wrote here for anyone who works on this issue in the future:

// index.d.ts
import type { configs, rules } from './src/index';

declare var plugin: {
  configs: typeof configs;
  rules: typeof rules;
};

export default plugin;
// src/index.d.ts
import type { Linter } from "eslint";

import type RulesOfHooks from './RulesOfHooks';
import type ExhaustiveDeps from './ExhaustiveDeps';

export const configs: {
  recommended: Linter.Config;
};

export const rules: {
  'rules-of-hooks': typeof RulesOfHooks;
  'exhaustive-deps': typeof ExhaustiveDeps;
};
// both src/RulesOfHooks.d.ts and src/ExhaustiveDeps.d.ts
import type { Rule } from "eslint";

declare var rule: Rule.RuleModule;

export default rule;

Copy link

This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!

@github-actions github-actions bot added the Resolution: Stale Automatically closed due to inactivity label Sep 28, 2024
@divergentdave
Copy link

bump

Copy link

This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!

@github-actions github-actions bot added the Resolution: Stale Automatically closed due to inactivity label Dec 27, 2024
@kutsan
Copy link

kutsan commented Dec 27, 2024

Not stale.

@github-actions github-actions bot removed the Resolution: Stale Automatically closed due to inactivity label Dec 27, 2024
@Rick-Phoenix
Copy link

Such an annoying issue with many eslint plugins.

@kachkaev
Copy link
Contributor

kachkaev commented Jan 4, 2025

This issue also applies to eslint-plugin-react-compiler. A fix could cover both packages at once.

@hello-rory
Copy link

Not stale.

@michaelfaith
Copy link
Contributor

I can take this up once #30774 lands.

@kachkaev
Copy link
Contributor

@michaelfaith, #30774 is in. Are you still up for adding typings to eslint-plugin-react-hooks and eslint-plugin-react-compiler? Happy to help if you no longer have enough capacity.

@michaelfaith
Copy link
Contributor

michaelfaith commented Jan 23, 2025

@michaelfaith, #30774 is in. Are you still up for adding typings to eslint-plugin-react-hooks and eslint-plugin-react-compiler? Happy to help if you no longer have enough capacity.

I've started working on converting the hooks plugin to TypeScript entirely (rather than just adding declaration files), in preparation for merging the two plugins. One outcome of that will be type declarations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug
Projects
None yet
7 participants