TypeScript生成.d.ts声明文件时如何排除内部导出类型?
问题描述
我正在编写一道面试题,通过创建一个「Http Client」包来模拟后端服务器。我希望部分类型能暴露在.d.ts文件中给面试者提供上下文,但绝大多数类型不能暴露,因为它们会泄露模拟服务的内部实现,还会把我希望面试者自行生成的类型提前给到他们。
src/index.ts
import myPackageExport from './my-package-export'; export * from './public-types'; export { MyPackageExport } from './my-package-export'; export default myPackageExport;
我希望可以直接在tsconfig.json和/或webpack.config.js中配置相关规则实现需求,示例配置如下:
tsconfig.json
{ "compilerOptions": { // ... "noEmit": true, // 我也尝试过设为false "declaration": true, "emitDeclarationOnly": true, "rootDir": "./src", "outDir": "./lib", }, "include": [ "./src/index.ts" ], // ... }
webpack.config.js
// ... module.exports = { entry: path.join(__dirname, 'src/index.ts'), output: { filename: 'index.js', path: path.join(__dirname, 'lib'), }, // ... module: { rules: [ { test: /\.ts$/, use: [ 'ts-loader' ], }, ], }, resolve: { extensions: [ '.js', '.ts' ], }, plugins: [ // 这里可以加声明生成相关的插件 ], };
但这套配置会生成index.ts整个依赖树(也就是整个项目)的声明文件,通常这是符合预期的效果,但不符合我当前的需求。要是有类似// @ts-exclude-declaration的注释可以加在要排除声明的文件头部就好了,但据我所知目前没有这样的功能。
我当前的临时解决方案是新增/修改三个文件:
src/public-types/index.ts(修改后)
export * from './my-public-types1'; // ... export interface MyPackageExport { // ... } declare const myPackageExport: MyPackageExport; export default myPackageExport;
tsconfig.types.json(新增)
{ "extends": "./tsconfig.json", "compilerOptions": { // ... "declaration": true, "emitDeclarationOnly": true, "rootDir": "./src/public-types", "outDir": "./lib", }, "include": [ "./src/public-types/index.ts" ], }
package.json(修改后)
{ "scripts": { "build": "webpack --mode production && tsc -p tsconfig.types.json", // ... }, // ... }
这个方案可以正常运行,但不够优雅,请问有没有更好的实现思路?
解决方案
给你两个更简洁的实现思路,不用维护多套tsconfig和重复的类型定义:
方案1:手动维护公开类型入口
直接关闭TS自动生成声明的能力,所有公开类型手动维护在单独的.d.ts文件里,通过package.json指定类型入口即可:
- 删掉tsconfig里的
declaration、emitDeclarationOnly相关配置,ts-loader只负责转译TS生成JS产物 - 手动创建
types/index.d.ts,把要公开的类型全部写在这里 - 在package.json中添加配置:
{ "types": "./types/index.d.ts", "typesVersions": { "*": { "*": ["./types/index.d.ts"] } } }
这种方式适合公开类型不多的场景,完全可控,不会泄露任何内部类型,维护成本也很低。
方案2:用dts-bundle-generator插件打包声明文件
如果公开类型较多,不想手动维护,可以用这个插件,它只会提取入口文件中导出的公开类型,自动把所有依赖的类型打包成单个.d.ts文件,不会暴露内部未导出的类型:
- 安装依赖:
npm i dts-bundle-generator -D - 修改package.json的build脚本:
{ "scripts": { "build": "webpack --mode production && dts-bundle-generator --out-file ./lib/index.d.ts ./src/index.ts" } }
不需要额外的tsconfig配置,插件会自动读取你现有的tsconfig规则,生成的产物只有一个index.d.ts,包含的全是你在入口文件导出的公开类型,内部依赖的未导出类型会被自动剔除。
内容的提问来源于stack exchange,提问作者dx_over_dt

