Typescript不会将d.ts文件复制到构建目录

80

也许我有些困惑,但我认为如果我在tsconfig.json中添加declaration:true,那么tsc可以将我的*.d.ts文件与转换后的代码及其d.ts文件一起复制过去?

例如:

- src
 - lib
   - types.d.ts
   - foo.ts

我希望tsc的结果类似于:

- build
 - lib
   - types.d.ts
   - foo.js
   - foo.d.ts

不过,我似乎无法将types.d.ts复制到我的构建目录中。

typescript没有提供任何复制.d.ts文件的机制吗?还是我某个地方配置错误了?(我尝试了很多不同的配置;似乎都不起作用)


似乎 declaration:true 仅适用于从 .ts 文件中创建声明... 仍然感觉非常奇怪,没有一种简单的方法可以轻松地将我的环境 .d.ts 文件复制到构建中。 - NSjonas
2个回答

105
你是正确的 - declaration:true 意味着只有在每个给定的 .ts 文件中,tsc 会生成并复制相应的 .d.ts 输出文件到 build 目录(如果适用,还包括 .js.map)。因此,tsc 不会将你的自定义 types.d.ts 文件复制到输出目录。
基本上,.d.ts 文件被视为编译器进行类型检查的不可修改的输入。它们不用于任何输出生成,这也意味着它们不会被复制到 build 中。你可以在这里阅读更多维护者的观点:

你使用的 .d.ts 文件是构建系统的输入,但不是输出。从 .d.ts 中消耗一些类型是完全合理的,但你的输出不使用这些类型,因此没有理由将输入的 .d.ts 与构建结果一起分发。[...] 这听起来你需要一个后置构建步骤来将相关的 .d.ts 文件复制到你需要的地方。

.d.ts 文件被认为是“引用”,编译器不会处理它们,不会移动它们或重新创建它们。一个简单的思路是将 .d.ts 文件与 .js 文件一起使用。如果你正在复制 .js 文件,那么应该复制相匹配的 .d.ts。

解决方案 #1:通过手动构建步骤复制 d.ts 文件

一种可能的解决方案是在构建步骤中手动复制所有需要的.d.ts文件,例如types.d.ts。具体工具取决于项目和构建类型、操作系统等因素。该工具应当在将文件复制到build时保留src目录结构,以便import类型引用仍然有效。其中一些工具包括:cp --parents(shell)、rsyncrobocopy或像copyfiles这样的平台无关的npm包。
"scripts": {
  "copy-dts": "copyfiles -u 1 \"src/**/*.d.ts\" build"
}

解决方案2:将.d.ts文件重命名为.ts扩展名
将你的.d.ts文件重命名为.ts扩展名(或将类型重新集成到现有的.ts文件中),这样tsc就会负责在输出中发出声明。轻微的缺点是,你没有编译器强制实施类型和实现代码之间的分离(.d.ts文件不允许包含代码)。最大的优点是,你不需要额外的构建步骤。
在我看来,后者是生成公共API的最简单方法,例如你的npm包,而.d.ts文件可以成为内部使用和共享类型声明的候选项。

1
我的做法是将全局类型都写在一个.ts文件中,您认为这种方法有什么弊端吗? - NSjonas
@NSjonas 更新了我的答案,也提到了你使用 .ts 文件进行类型定义的方法。 - ford04
15
值得一提的是,解决方案#2也会导致编译器创建一个空的js文件。 - elad.chen
6
很遗憾这是目前的解决方案。对于生成的protobuf文件来说,处理起来非常烦人。 - Nathanael

0
使用package.json "files" field来包含类型定义文件。您的类型定义不会被复制到构建目录中,但生成的包仍将包含它们。
"files": [
    "build",
    "src/**/*.d.ts"
  ]

生成的类型声明文件将自动维护对全局声明文件的任何引用。
/// <reference path="../src/types.d.ts" />

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接