如何在TypeScript私有NPM包中正确导出类型
实现私有NPM包的子路径ES模块导入
1. 调整TypeScript编译配置,保持输出结构与源码一致
修改tsconfig.json,让编译后的文件结构和src完全对应,同时直接输出.mjs文件避免手动改名:
{ "compilerOptions": { "target": "es2016", "lib": ["ES2015"], // Node.js包无需DOM库 "module": "ESNext", // 适配Node.js ES模块特性 "moduleResolution": "node16", // 匹配Node.js 16+的模块解析逻辑,支持子路径导出 "declaration": true, "outDir": "./dist", "declarationDir": "./dist/types", "esModuleInterop": true, "skipLibCheck": true, "resolveJsonModule": true, "allowSyntheticDefaultImports": true, "outExtension": { ".js": ".mjs" } // 直接生成.mjs后缀文件 }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"] }
2. 修改package.json,配置子路径导出映射
在exports字段中添加每个需要暴露的子路径,同时声明包为ES模块:
{ "name": "packmodpoc", "version": "1.0.0", "type": "module", // 必须声明,告诉Node.js这是ES模块包 "typings": "dist/types/index.d.ts", "exports": { ".": { "import": { "types": "./dist/types/index.d.ts", "default": "./dist/index.mjs" } }, "./Constants/Oidc": { "import": { "types": "./dist/types/Constants/Oidc.d.ts", "default": "./dist/Constants/Oidc.mjs" } }, "./Constants": { // 可选:暴露Constants目录的聚合导出 "import": { "types": "./dist/types/Constants/index.d.ts", "default": "./dist/Constants/index.mjs" } } }, "files": [ "dist/**/*" ], "scripts": { "clean": "rm -rf ./dist", "build": "npm run clean && npx tsc -p ./tsconfig.json", // 无需手动改名 "prepack": "npm run build" }, "devDependencies": { "tslib": "^2.6.2", "typescript": "^5.2.2" } }
3. 确认源码导出结构
src/Constants/Oidc.ts保持默认导出:
export default class Oidc { // 示例常量 static readonly AUTH_ENDPOINT = "https://your-oidc-server.com/auth"; }
src/Constants/index.ts保持聚合导出:
export { default as Oidc } from "./Oidc";
src/index.ts可按需导出顶层内容:
export * from "./Constants";
4. 验证消费端导入
发布包或本地通过npm link测试后,消费端可按预期导入:
// 直接导入Oidc默认导出 import Oidc from "packmodpoc/Constants/Oidc"; // 从Constants目录导入聚合导出 import { Oidc } from "packmodpoc/Constants"; // 从包顶层导入 import { Oidc } from "packmodpoc";
关键注意事项
moduleResolution: "node16"是Node.js ES模块子路径导出的必要配置,比旧的node模式更精准。type: "module"必须添加,否则Node.js会将包当作CommonJS处理,导致ES模块导入失败。exports字段的路径必须与编译后的文件结构完全对应,Node.js会严格按照该映射查找模块。
内容的提问来源于stack exchange,提问作者onefootswill
相关产品推荐
相关产品推荐

