导出原始 .ts 文件而不是 .d.ts 文件作为模块类型声明的后果

Posted

技术标签:

【中文标题】导出原始 .ts 文件而不是 .d.ts 文件作为模块类型声明的后果【英文标题】:Ramifications of exporting original .ts files instead of .d.ts files as module type declarations 【发布时间】:2019-06-21 06:46:44 【问题描述】:

典型的 TypeScript 模块包含带有 TypeScript 源代码文件的 src 目录,运行 tsc -d --outDir dist 以将源代码编译为 dist,并设置以下包元数据以让 Node.js 运行时和 TypeScript 编译器都了解模块正在导出:


  "main": "dist/index.js",
  "types": "dist/index.d.ts",
  "files": ["dist"]

为了使调试更容易,通常需要软件包提供源映射和原始源代码。

使用最近引入的Project References 和编译器选项--declarationMap,我觉得模块也应该提供声明映射文件,以允许IDE 从调用模块API 的地方直接跳转到实现,而不是生成的.d.ts文件。

因此,一个模块将打包以下文件:

转译了运行时所需的 .js 文件 调试所需的原始.ts 文件 TypeScript 编译器需要 .d.ts 中的声明 IDE 工具需要 .d.ts.map 中的声明映射

这个设置对我来说似乎过于复杂并引出了一个问题 - 如果我们摆脱 .d.ts.d.ts.map 文件并提供原始 TypeScript 源代码会怎样?


  "main": "dist/index.js",
  "types": "src/index.ts",
  "files": ["src", "dist"]

我想到的几个缺点:

根据我的模块编译项目时,TypeScript 编译器将有更多工作要做。它必须解析完整的.ts 源,而不是解析密集的.d.ts 文件。结果,构建可能会变慢。

对于 VSCode 等 IDE 也是如此:语言服务必须解析完整的 .ts 源,而不是加载最有可能针对快速解析进行优化的 .d.ts.map 文件。

.d.ts.ts 文件之间也存在细微差别。前者仅导出声明(例如declare class Foo ),而后者导出定义(例如class Foo )。我并不完全熟悉 TypeScript 如何处理依赖关系树中存在同一模块的多个实例的情况。它会以不同的方式处理声明的多个副本与定义的多个副本吗?

还有其他反对使用原始 .ts 文件作为类型声明的论据吗?

【问题讨论】:

【参考方案1】:

通常需要软件包来提供源映射和原始 源代码也是。

这部分是正确的。源地图确实包含您的源代码。这就是为什么只要存在源映射,DevTools 就能够从缩小的 javascript 代码重新创建原始源。

我可以看到的一个缺点是您的包裹的大小。声明文件是轻量级的。大多数库可能都可以用一个小于 100 行代码的声明文件来描述。

然而,小的 API 表面并不意味着没有太多的源代码。你可以有一个包含数千个模块的项目,但它的公共 API 是一个单一的接口。使用*.d.ts 文件来描述它可以让您的消费者在他们的机器上节省大量空间。

【讨论】:

以上是关于导出原始 .ts 文件而不是 .d.ts 文件作为模块类型声明的后果的主要内容,如果未能解决你的问题,请参考以下文章

如果库的实现未与 TS 项目集成,如何使用 d.ts 文件导出的 const 类型?

使用复杂的 .d.ts 文件 (chrome-app.d.ts)

typeScript声明文件的一个注意点:不能使用导入导出语法

TypeScript 接口是不是应该在 *.d.ts 文件中定义

要求 NPM 下载 TypeScript 源代码,而不仅仅是 *.d.ts 文件

解决 npm 包提供的错误 index.d.ts 文件