多平台UI Kit嵌套导出的TypeScript类型定义问题
目标
我想要构建一套能同时被Web应用和React Native应用使用的UI Kit,明确要求不使用react-native-web。
解决方案思路
计划创建带有共享接口层的UI Kit,通过嵌套目录导出@abc/ui-kit/web和@abc/ui-kit/native两个模块,尝试用package.json的exports字段实现单包多平台导出。
遇到的问题
导入UI Kit时,TypeScript抛出模块缺失错误:
import { Button } from '@abc/ui-kit'; import { Button } from '@abc/ui-kit/web';
找不到模块'@abc/ui-kit'或其相应的类型声明
找不到模块'@abc/ui-kit/web'或其相应的类型声明
当前UI Kit的package.json中exports配置如下:
"exports": { "web": { "types": "./dist/web/index.d.ts", "default": "./dist/web/index.ts" }, "native": { "types": "./dist/native/index.d.ts", "default": "./dist/native/index.ts" } }
dev分支的v1版本可正常运行,v2版本改用exports实现多平台导出后失效。想确认该方案是否可行,还是需要重构应用?
解决方案
这个方案完全可行,问题出在exports配置的完整性和TypeScript的模块解析逻辑上,只需调整以下几点即可修复:
1. 补全exports的路径配置
当前配置仅包含条件平台导出,缺少根模块(@abc/ui-kit)和子路径(@abc/ui-kit/web/native)的显式声明。调整后的exports应包含:
"exports": { // 根模块,根据环境自动切换 ".": { "web": { "types": "./dist/web/index.d.ts", "default": "./dist/web/index.ts" }, "native": { "types": "./dist/native/index.d.ts", "default": "./dist/native/index.ts" }, "default": "./dist/web/index.ts" // 兜底默认平台 }, // 显式声明子路径入口 "./web": { "types": "./dist/web/index.d.ts", "default": "./dist/web/index.ts" }, "./native": { "types": "./dist/native/index.d.ts", "default": "./dist/native/index.ts" } }
2. 添加typesVersions配置
TypeScript对exports的类型解析需要额外的typesVersions字段来映射子路径类型:
"typesVersions": { "*": { "web": ["./dist/web/index.d.ts"], "native": ["./dist/native/index.d.ts"], ".": ["./dist/web/index.d.ts"] // 兜底类型 } }
3. 确保类型文件正确生成
在UI Kit的tsconfig.json中开启declaration: true,并设置outDir: "./dist",确保编译后dist/web和dist/native目录下生成对应的.d.ts文件,且文件中包含所有组件的类型声明。
4. 验证文件结构
确认dist/web/index.d.ts和dist/native/index.d.ts确实存在,且Button等组件的类型已正确导出。
无需重构应用,调整上述配置后即可实现单包多平台的正常导出和类型识别。
内容的提问来源于stack exchange,提问作者Spidy

