集成 TypeScript
TypeScript 是单体仓库中的优秀工具,允许团队安全地为 JavaScript 代码添加类型。虽然设置有一些复杂性,但本指南将引导你了解大多数用例的 TypeScript 设置的重要部分。
本指南假设你使用的是最新版本的 TypeScript,并使用了一些仅在这些版本中可用的功能。如果你无法使用这些版本的功能,可能需要调整本页面上的指导。
共享 tsconfig.json
你希望在 TypeScript 配置中构建一致性,以便整个仓库可以使用优秀的默认设置,你的团队成员在工作区中编写代码时能知道期望什么。
TypeScript 的 tsconfig.json
设置了 TypeScript 编译器的配置,并具有 extends
键,你将使用它在工作区之间共享配置。
本指南将使用 create-turbo
作为示例。
使用基础 tsconfig
文件
在 packages/typescript-config
中,你有几个 json
文件,代表了你可能想要在各种包中配置 TypeScript 的不同方式。base.json
文件被工作区中的每个其他 tsconfig.json
扩展,如下所示:
tsconfig
选项参考
创建包的其余部分
此包中的其他 tsconfig
文件使用 extends
键以基础配置开始,并为特定类型的项目进行自定义,如 Next.js(nextjs.json
)和 React 库(react-library.json
)。
在 package.json
中,命名包以便在工作区的其余部分引用:
构建 TypeScript 包
使用配置包
首先,将 @repo/typescript-config
包安装到你的包中:
然后,从 @repo/typescript-config
包扩展包的 tsconfig.json
。在这个例子中,web
包是一个 Next.js 应用程序:
创建包的入口点
首先,确保你的代码用 tsc
编译,这样会有一个 dist
目录。你需要一个 build
脚本和一个 dev
脚本:
然后,在 package.json
中设置包的入口点,以便其他包可以使用编译后的代码:
这样设置 exports
有几个优点:
- 使用
types
字段允许tsserver
使用src
中的代码作为代码类型的真实来源。你的编辑器将始终与代码中的最新接口保持同步。 - 你可以快速向包添加新的入口点,而无需创建危险的桶文件。
- 你将在编辑器中收到跨包边界的导入自动导入建议。
如果你正在发布包,你不能在 types
中使用对源代码的引用,因为只有编译后的代码会发布到
npm。你需要生成并引用声明文件和源映射。
代码库的检查
要使用 TypeScript 作为代码检查器,你可以使用 Turborepo 的缓存和并行化快速检查工作区中的类型。
首先,向你想要检查类型的任何包添加 check-types
脚本:
然后,在 turbo.json
中创建一个 check-types
任务。根据配置任务指南,我们可以使用传输节点让任务并行运行,同时尊重来自其他包的源代码更改:


然后,使用 turbo check-types
运行你的任务。
最佳实践
使用 tsc
编译你的包
对于内部包,我们建议尽可能使用 tsc
编译你的 TypeScript 库。虽然你可以使用打包器,但这并不是必需的,并且会给你的构建过程增加额外的复杂性。此外,打包库可能会在代码到达应用程序的打包器之前篡改代码,导致难以调试的问题。
启用跨包边界的转到定义
"转到定义"是一种编辑器功能,可以通过点击或热键快速导航到符号(如变量或函数)的原始声明或定义。一旦 TypeScript 配置正确,你可以轻松地在内部包之间导航。
即时包
来自即时包的导出将自动带你到原始的 TypeScript 源代码。转到定义将按预期工作。
编译包
来自编译包的导出需要使用 declaration
和 declarationMap
配置才能使转到定义工作。在为包启用这两个配置后,使用 tsc
编译包,并打开输出目录以查找声明文件和源映射。
有了这两个文件,你的编辑器现在将导航到原始源代码。
使用 Node.js 子路径导入而不是 TypeScript 编译器 paths
可以使用 TypeScript 编译器的 paths
选项 在包中创建绝对导入,但这些路径在使用即时包时可能导致编译失败。从 TypeScript 5.4 开始,你可以使用 Node.js 子路径导入作为更健壮的解决方案。
即时包
在即时包中,imports
必须针对包中的源代码,因为不会创建 dist
等构建输出。
编译包
在编译包中,imports
针对包的构建输出。
你可能不需要在项目根目录中的 tsconfig.json
文件
如构建你的仓库指南中所述,你希望将工具中的每个包视为自己的单元。这意味着每个包都应该有自己的 tsconfig.json
来使用,而不是引用项目根目录中的 tsconfig.json
。遵循这种做法将使 Turborepo 更容易缓存你的类型检查任务,简化你的配置。
你可能想要在工作区根目录中有一个 tsconfig.json
的唯一情况是为不在包中的 TypeScript 文件设置配置。例如,如果你有一个用 TypeScript 编写的需要从根目录运行的脚本,则可能需要为该文件提供 tsconfig.json
。
然而,也不建议这样做,因为工作区根目录中的任何更改都会导致所有任务错过缓存。相反,将这些脚本移动到仓库中的不同目录。
你可能不需要 TypeScript 项目引用
我们不建议使用 TypeScript 项目引用,因为它们在你的工作区中引入了另一个配置点和另一个缓存层。这两者都可能在你的仓库中引起问题,几乎没有好处,所以我们建议在使用 Turborepo 时避免使用它们。
限制
你的编辑器不会使用包的 TypeScript 版本
tsserver
无法在代码编辑器中为不同的包使用不同的 TypeScript 版本。相反,它将发现一个特定版本并在所有地方使用它。
这可能会导致在编辑器中显示的代码检查错误与运行 tsc
脚本检查类型时的错误之间存在差异。如果这对你来说是个问题,请考虑保持 TypeScript 依赖项在同一版本。