[eslint-plugin-react-hooks] 缺少类型声明

axzmvihb  于 5个月前  发布在  React
关注(0)|答案(2)|浏览(70)

版本:所有
严重性:低

问题

当在TypeScript环境中导入eslint-plugin-react-hooks时,会抛出一个"缺少类型声明"的错误。

原因

这是因为eslint-plugin-react-hooks包中没有包含任何类型声明。通常这些声明会在index.d.ts文件中。此外,eslint-plugin-react-hooks项目中也没有对应的@types/...包供用户依赖。

解决方法

用户可以按照错误信息中的说明,进行临时模块增强,为该包声明自己的类型。在我的项目中,我是这样做的:

// ./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;
}

但这种方法不会自动与包保持同步,也不能保证正确性。它还可能不完整,不包含插件中不同配置的详细信息。

如何修复

有几种方法。

  1. 通常首选的解决方案是将所有内容都写成TypeScript,并让它为你自动生成声明文件。但我明白如果完全重写不在议程上的话 :)
  2. 可以在DefinitelyTyped仓库中添加一个@types/eslint-plugin-react-hooks包。但这样你的类型就会在你的实际代码中定义在一个完全不同的地方,而且如果你以后决定迁移到TypeScript,旧的@types/...包需要被弃用。听起来很混乱。
  3. 在我看来,最佳解决方案是向包中添加一个index.d.ts文件,声明该包的类型导出。然后将其定义为package.json中的类型声明。简单易行。
// package.json
+  "main": "index.js",
+  "types": "index.d.ts",
  "files": [
    "LICENSE",
    "README.md",
    "index.js",
+    "index.d.ts",
    "cjs"
  ],

我很乐意自己来做这件事。我只是想先提交一个问题以确认维护者是否会批准。

重现步骤

  1. 安装typescript, eslint-plugin-react-hooks
  2. 创建一个.ts文件
  3. 导入eslint-plugin-react-hooks

代码示例

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';

(你还需要一个tsconfig.json文件,但设置对此示例无关)

当前行为

TypeScript构建错误。

预期行为

无错误。

b5lpy0ml

b5lpy0ml1#

在尝试自己添加一个 index.d.ts 声明文件后,我很快意识到我并不理解这个 monorepo 的构建/捆绑系统。声明文件被排除在构建输出之外。
我找到了两个不同的 TODO 注解,解释了当前的构建过程对于一个 eslint 插件来说并不是很好。
./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.

修复这个问题也将允许将声明文件添加到发布的包中,而不是被打包器忽略。
这让我想知道 eslint-plugin-react-hooks 是否应该像大多数独立的 npm 包一样放在自己的仓库里,以避免 monorepo 捆绑系统不适合它的尴尬情况。但我会把这个决定留给维护者。

slmsl1lt

slmsl1lt2#

我打算把这里写的声明文件分享给未来在这个问题上工作的人:

// 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;

相关问题