内部npm包导入路径异常,如何实现根路径直接导入类型?
问题
我有一个用于构建并推送到内部包注册表的package.json配置如下:
{ "name": "@internal/my-project", "version": "0.0.0", "description": "Test package", "type": "commonjs", "bin": { "my-project": "./dist/src/index.js" }, "files": [ "dist" ], "exports": { ".": { "import": "./dist/src/index.js", "types": "./dist/src/index.d.ts" }, "./models": { "import": "./dist/src/models/index.js", "types": "./dist/src/models/index.d.ts" } }, "scripts": { "build": "tsc --project tsconfig.build.json" }, "dependencies": { "tslib": "^2.3.0" }, "engines": { "node": ">=18" }, "volta": { "node": "18.16.1" }, "publishConfig": { "registry": "https://internal.com/" } }
项目文件结构:
my-project src/ -> lib/ -> models/ -> my-model.ts -> index.ts -> index.ts package.json
构建后的dist目录结构:
my-project -> dist/ -> src/ -> lib/ -> models/ -> index.js -> index.d.ts -> tsconfig.build.tsbuildinfo
同时配置了tsconfig.build.json和tsconfig.json:
{ "compilerOptions": { "types": [ "node" ], "composite": true }, "extends": "./tsconfig.json", "include": [ "src/**/*.ts" ], "exclude": [ "src/**/*.spec.ts", "dist/**/*" ] }
{ "compilerOptions": { "rootDir": ".", "declaration": true, "moduleResolution": "node", "emitDecoratorMetadata": true, "experimentalDecorators": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "importHelpers": true, "allowJs": true, "strict": true, "strictNullChecks": true, "noImplicitReturns": true, "strictPropertyInitialization": false, "resolveJsonModule": true, "noFallthroughCasesInSwitch": true, "target": "ES6", "module": "CommonJS", "lib": [ "ES6", "dom" ], "skipLibCheck": true, "skipDefaultLibCheck": true, "baseUrl": ".", "forceConsistentCasingInFileNames": true, "outDir": "./dist" }, "references": [ { "path": "./tsconfig.build.json" }, { "path": "./tsconfig.spec.json" } ] }
我将该包构建并打包为本地tgz归档文件后,在另一个项目中安装:
{ "name": "test-app", "version": "1.0.0", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "description": "", "devDependencies": { "ts-node": "^10.9.2", "typescript": "^5.3.3" }, "dependencies": { "@internal/my-project": "file:../../../my-project/internal-my-project-0.0.0.tgz" } }
但导入MyModel中的类型时,必须使用如下路径:
import { IModel } from '@internal/my-project/dist/src/models/my-model';
而我期望的导入方式是:
import { IModel } from '@internal/my-project';
请问这是配置错误导致的,还是预期行为?我希望无需指定包内完整路径即可导入类型。
解答
这是配置错误导致的,并非预期行为。要实现你期望的导入方式,需要调整以下几处配置:
1. 统一导出类型到包入口
在my-project/src/index.ts中,将models目录下的所有导出内容重新导出到包的入口文件:
// src/index.ts export * from './models';
这样包的入口就会包含models里的所有类型和变量,用户直接导入包名就能获取这些内容。
2. 调整TypeScript编译的根目录
当前tsconfig.json中rootDir设为.,会导致编译后的文件保留src目录层级。将rootDir改为./src,编译产物会直接输出到dist根目录:
// tsconfig.json { "compilerOptions": { "rootDir": "./src", // 修改此处 // 其他配置保持不变 } }
修改后,构建后的dist结构会变为:
my-project -> dist/ -> lib/ -> models/ -> index.js -> index.d.ts -> tsconfig.build.tsbuildinfo
3. 更新package.json中的路径配置
对应调整package.json里的bin、exports路径,去掉多余的src层级:
{ "bin": { "my-project": "./dist/index.js" }, "exports": { ".": { "import": "./dist/index.js", "types": "./dist/index.d.ts" }, "./models": { "import": "./dist/models/index.js", "types": "./dist/models/index.d.ts" } } }
4. 确认打包内容范围
确保package.json的files字段包含dist,保证所有编译产物都能被打包进tgz文件。
完成以上调整后,重新构建并打包,在测试项目中安装后,就能用import { IModel } from '@internal/my-project';的方式导入类型了。
内容的提问来源于stack exchange,提问作者code share
相关产品推荐
相关产品推荐

