多TypeScript项目中如何禁止跨项目导入内部模块?
限制TypeScript项目仅暴露指定模块给外部引用
问题场景
现有两个TypeScript项目结构如下:
├── proj_1 │ ├── hidden │ │ └── hidden-class.mts │ ├── index.mts │ ├── visible-class.mts │ └── tsconfig.json └── proj_2 ├── main.mts └── tsconfig.json
proj_1的tsconfig配置:
{ "compilerOptions": { "rootDir": ".", "baseUrl": ".", "target": "ESNext", "module": "ESNext", "moduleResolution": "node", "composite": true // 作为库构建 }, "references": [], "include": ["*", "**/*"], }
proj_2的tsconfig配置:
{ "compilerOptions": { "rootDir": ".", "baseUrl": ".", "target": "ESNext", "module": "ESNext", "moduleResolution": "node", "composite": true, "paths": { "~/proj_1/index.mjs": ["../proj_1/index.mjs"] } }, "references": [ { "path": "../proj_1/" } ], "include": ["*", "**/*"], }
当前问题:proj_1仅希望外部通过index.mts导入VisibleClass,但proj_2仍能通过相对路径直接导入内部的HiddenClass:
// proj_2/main.mts import { VisibleClass } from "~/proj_1/index.mjs"; // 本应报错,但目前可以正常导入 import { HiddenClass } from "../proj_1/hidden/hidden-class.mjs"; const v = new VisibleClass(); const h = new HiddenClass(); // 本应报错
解决方案
方法1:使用package.json的exports字段(推荐)
在proj_1根目录创建package.json,通过exports字段精确控制对外暴露的路径,禁止访问内部模块:
{ "name": "proj_1", "type": "module", "exports": { ".": "./index.mts", // 仅暴露根路径指向index.mts "./": null // 禁止所有子路径的外部访问 } }
同时调整proj_2的tsconfig路径映射,直接映射到proj_1包名:
"paths": { "proj_1": ["../proj_1/index.mts"] }
之后proj_2只能通过包名导入暴露的模块:
import { VisibleClass } from "proj_1"; // 尝试导入内部路径会触发TypeScript错误 import { HiddenClass } from "../proj_1/hidden/hidden-class.mjs"; // 报错
方法2:从proj_1的tsconfig控制类型暴露
在proj_1的tsconfig中添加declaration和declarationMap,并调整include/exclude,仅生成暴露模块的类型文件:
{ "compilerOptions": { "rootDir": ".", "baseUrl": ".", "target": "ESNext", "module": "ESNext", "moduleResolution": "node", "composite": true, "declaration": true, // 生成类型声明文件 "declarationMap": true }, "references": [], "include": ["index.mts", "visible-class.mts"], // 仅包含需要暴露的文件 "exclude": ["hidden/**/*"] // 排除内部模块 }
这种方式会阻止内部模块的类型文件生成,外部导入时会提示找不到类型,但仍可能通过运行时路径访问,因此建议配合方法1使用。
方法3:在proj_2中限制导入路径
在proj_2的tsconfig中添加exclude,禁止导入proj_1的内部目录:
"exclude": ["../proj_1/hidden/**/*"]
同时可以结合ESLint规则(如no-restricted-imports)进一步限制导入路径,但这属于消费端的被动限制,不如源端控制彻底。
内容的提问来源于stack exchange,提问作者jayatubi
相关产品推荐
相关产品推荐

