如何使用ESLint强制要求文件导出指定名称的命名导出?
需求实现方案
该需求完全可以实现,分为ESLint强制导出校验、TypeScript类型约束两部分:
一、自定义ESLint规则实现强制导出指定命名
现成的三方ESLint插件没有完全匹配的规则,自己实现自定义规则成本极低,步骤如下:
- 在项目根目录新建
.eslint-rules文件夹,创建规则文件require-named-exports.js,代码如下:
module.exports = { meta: { type: "problem", docs: { description: "要求指定目录下的文件必须导出对应名称的变量", }, fixable: null, schema: [ { type: "object", properties: { targetDir: { type: "string", description: "要校验的目录路径,相对项目根目录" }, requiredExports: { type: "array", items: { type: "string" }, description: "强制要求导出的命名列表" } }, additionalProperties: false } ] }, create(context) { const options = context.options[0] || {}; const targetDir = options.targetDir || "src/pages"; const requiredExports = options.requiredExports || ["config"]; // 仅校验目标目录下的文件 const fileName = context.getFilename(); if (!fileName.includes(targetDir)) return {}; let hasTargetExport = false; return { ExportNamedDeclaration(node) { // 遍历所有命名导出,检查是否包含要求的导出名 node.specifiers.forEach(spec => { if (requiredExports.includes(spec.exported.name)) { hasTargetExport = true; } }); if (node.declaration?.declarations) { node.declaration.declarations.forEach(decl => { if (requiredExports.includes(decl.id.name)) { hasTargetExport = true; } }); } }, "Program:exit"() { // 程序遍历结束后检查是否缺少要求的导出 if (!hasTargetExport) { context.report({ node: context.getSourceCode().ast, message: `该文件属于${targetDir}目录,必须导出以下命名:${requiredExports.join("、")}` }); } } }; } };
- 配置ESLint引入自定义规则,修改项目根目录的
.eslintrc.js:
module.exports = { // 其他原有配置... rulePaths: ["./.eslint-rules"], // 声明自定义规则的存放目录 rules: { // 启用自定义规则 "require-named-exports": ["error", { targetDir: "src/pages", requiredExports: ["config"] }] } };
配置完成后,所有src/pages下的文件如果没有导出config就会触发ESLint报错。
二、TypeScript场景下的config类型约束
方案1:手动标注类型
先定义公共的config类型:
// src/types/page.ts export interface PageConfig { // 按需定义你的config字段,示例如下 title: string; needAuth?: boolean; layout?: "default" | "blank" | "admin"; }
在页面文件中导出时直接标注类型,不符合结构会直接触发TS报错:
// src/pages/index.tsx import type { PageConfig } from "@/types/page"; export const config: PageConfig = { title: "首页", needAuth: true };
方案2:全局模块类型约束(可选)
如果不想每个文件都手动写类型注解,可以增加全局模块声明,所有导入src/pages下模块的位置都会自动校验导出类型:
// src/types/global.d.ts import type { PageConfig } from "./page"; import type { ReactNode } from "react"; declare module "*/src/pages/*.tsx" { export const config: PageConfig; export const Page: () => ReactNode; }
内容的提问来源于stack exchange,提问作者j_d
相关产品推荐
相关产品推荐

