TypeScript
TypeScript 是 monorepos 中的一个优秀工具,允许团队安全地将类型添加到他们的 JavaScript 代码中。虽然设置起来有些复杂,但本指南将引导你完成大多数用例中 TypeScript 设置的重要部分。
¥TypeScript is an excellent tool in monorepos, allowing teams to safely add types to their JavaScript code. While there is some complexity to getting set up, this guide will walk you through the important parts of a TypeScript setup for most use cases.
本指南假设你正在使用最新版本的 TypeScript,并使用一些仅在这些版本中可用的功能。如果你无法使用这些版本的功能,你可能需要调整此页面上的指南。
¥This guide assumes you are using a recent version of TypeScript and uses some features that are only available in those versions. You may need to adjust the guidance on this page if you are unable to features from those versions.
共享 tsconfig.json
¥Sharing tsconfig.json
你希望在 TypeScript 配置中建立一致性,以便你的整个代码库可以使用良好的默认值,并且你的其他开发者在工作区中编写代码时能够了解预期的内容。
¥You want to build consistency into your TypeScript configurations so that your entire repo can use great defaults and your fellow developers can know what to expect when writing code in the Workspace.
TypeScript 的 tsconfig.json
设置了 TypeScript 编译器的配置,并提供了一个 extends
键,你可以使用它在整个工作区中共享配置。
¥TypeScript's tsconfig.json
sets the configuration for the TypeScript compiler and features an extends
key that you'll use to share configuration across your workspace.
本指南将以 create-turbo
为例。
¥This guide will use create-turbo
as an example.
使用基础 tsconfig
文件
¥Use a base tsconfig
file
在 packages/typescript-config
文件中,有几个 json
文件,它们代表了你可能希望在各个包中配置 TypeScript 的不同方式。base.json
文件由工作区中的所有其他 tsconfig.json
文件扩展,如下所示:
¥Inside packages/typescript-config
, you have a few json
files which represent different ways you might want to configure TypeScript in various packages. The base.json
file is extended by every other tsconfig.json
in the workspace and looks like this:
tsconfig
选项参考
¥tsconfig
options reference
创建其余部分包
¥Creating the rest of the package
此包中的其他 tsconfig
文件使用 extends
键,以基本配置启动,并针对特定类型的项目进行自定义,例如 Next.js (nextjs.json
) 和 React 库 (react-library.json
)。
¥The other tsconfig
files in this package use the extends
key to start with the base configuration and customize for specific types of projects, like for Next.js (nextjs.json
) and a React library (react-library.json
).
在 package.json
文件中,为包命名,以便可以在工作区的其余部分引用它:
¥Inside package.json
, name the package so it can be referenced in the rest of the Workspace:
构建 TypeScript 软件包
¥Building a TypeScript package
使用配置包
¥Using the configuration package
首先,将 @repo/typescript-config
包安装到你的包中:
¥First, install the @repo/typescript-config
package into your package:
然后,从 @repo/typescript-config
包中扩展包的 tsconfig.json
。在此示例中,web
包是一个 Next.js 应用:
¥Then, extend the tsconfig.json
for the package from the @repo/typescript-config
package. In this example, the web
package is a Next.js application:
创建包的入口点
¥Creating entrypoints to the package
首先,确保你的代码使用 tsc
编译,这样就会有一个 dist
目录。你需要一个 build
脚本和一个 dev
脚本:
¥First, make sure your code gets compiled with tsc
so there will be a dist
directory. You'll need a build
script as well as a dev
script:
然后,在 package.json
中为你的包设置入口点,以便其他包可以使用编译后的代码:
¥Then, set up the entrypoints for your package in package.json
so that other packages can use the compiled code:
以这种方式设置 exports
有几个优点:
¥Setting up exports
this way has several advantages:
-
使用
types
字段允许tsserver
使用src
中的代码作为代码类型的真实来源。你的编辑器将始终使用你代码中的最新接口保持更新。¥Using the
types
field allowstsserver
to use the code insrc
as the source of truth for your code's types. Your editor will always be up-to-date with the latest interfaces from your code. -
你可以快速向包中添加新的入口点,而无需创建 危险的桶文件。
¥You can quickly add new entrypoints to your package without creating dangerous barrel files.
-
你将在编辑器中收到跨包导入的自动导入建议。
¥You'll receive auto-importing suggestions for your imports across package boundaries in your editor.
如果你要发布软件包,则无法在 types
中使用对源代码的引用,因为只有编译后的代码才会发布到 npm。你需要生成并引用声明文件和源映射。
¥If you're publishing the package, you cannot use references to source code in
types
since only the compiled code will be published to npm. You'll need to
generate and reference declaration files and source maps.
代码库的 Linting
¥Linting your codebase
要将 TypeScript 用作 linter,你可以使用 Turborepo 的缓存和并行化功能快速检查整个工作区的类型。
¥To use TypeScript as a linter, you can check the types across your workspace fast using Turborepo's caching and parallelization.
首先,向任何你想要检查类型的包添加一个 check-types
脚本:
¥First, add a check-types
script to any package that you want to check the types for:
然后,在 turbo.json
中创建一个 check-types
任务。从 配置任务指南 开始,我们可以使用 Transit Node 使任务并行运行,同时尊重其他软件包的源代码更改:
¥Then, create a check-types
task in turbo.json
. From the Configuring tasks guide, we can make the task run in parallel while respecting source code changes from other packages using a Transit Node:


然后,使用 turbo check-types
运行你的任务。
¥Then, run your task using turbo check-types
.
最佳实践
¥Best practices
使用 tsc
编译你的软件包
¥Use tsc
to compile your packages
对于 内部软件包,我们建议你尽可能使用 tsc
来编译 TypeScript 库。虽然你可以使用打包器,但它不是必需的,而且会增加构建过程的复杂性。此外,打包库可能会在代码到达应用的打包器之前对其进行破坏,从而导致难以调试的问题。
¥For Internal Packages, we recommend that you use tsc
to compile your TypeScript libraries whenever possible. While you can use a bundler, it's not necessary and adds extra complexity to your build process. Additionally, bundling a library can mangle the code before it makes it to your applications' bundlers, causing hard to debug issues.
启用跨包边界的跳转定义
¥Enable go-to-definition across package boundaries
"跳转至定义" 是一项编辑器功能,可通过单击或热键快速导航到符号(如变量或函数)的原始声明或定义。正确配置 TypeScript 后,你可以轻松在 内部软件包 中导航。
¥"Go-to-definition" is an editor feature for quickly navigating to the original declaration or definition of a symbol (like a variable or function) with a click or hotkey. Once TypeScript is configured correctly, you can navigate across Internal Packages with ease.
即时软件包
¥Just-in-Time Packages
从 即时软件包 导出将自动转到原始 TypeScript 源代码。跳转定义功能将按预期工作。
¥Exports from Just-in-Time Packages will automatically bring you to the original TypeScript source code. Go-to-definition will work as expected.
已编译的软件包
¥Compiled Packages
从 已编译的软件包 导出需要使用 declaration
和 declarationMap
配置才能实现跳转定义功能。为包启用这两个配置后,使用 tsc
编译包,然后打开输出目录以查找声明文件和源映射。
¥Exports from Compiled Packages require the use of declaration
and declarationMap
configurations for go-to-definition to work. After you've enabled these two configurations for the package, compile the package with tsc
, and open the output directory to find declaration files and source maps.
有了这两个文件,你的编辑器现在将导航到原始源代码。
¥With these two files in place, your editor will now navigate to the original source code.
使用 Node.js 子路径导入,而不是 TypeScript 编译器 paths
¥Use Node.js subpath imports instead of TypeScript compiler paths
可以使用 TypeScript 编译器的 paths
选项 在包中创建绝对导入,但使用 即时软件包 时,这些路径可能会导致编译失败。自 TypeScript 5.4 起,你可以使用 Node.js 子路径导入 来获得更强大的解决方案。
¥It's possible to create absolute imports in your packages using the TypeScript compiler's paths
option, but these paths can cause failed compilation when using Just-in-Time Packages. As of TypeScript 5.4, you can use Node.js subpath imports instead for a more robust solution.
即时软件包
¥Just-in-Time Packages
在 Just-in-Time 包 中,imports
必须以包中的源代码为目标,因为不会创建像 dist
这样的构建输出。
¥In Just-in-Time packages, imports
must target the source code in the package, since build outputs like dist
won't be created.
已编译的软件包
¥Compiled Packages
在 编译包 中,imports
以包的构建输出为目标。
¥In Compiled packages, imports
target the built outputs for the package.
你可能不需要在项目根目录中放置 tsconfig.json
文件
¥You likely don't need a tsconfig.json
file in the root of your project
正如 构建仓库指南 中提到的,你需要将工具中的每个包视为独立的单元。这意味着每个包都应该有自己的 tsconfig.json
可供使用,而不是在项目根目录中引用 tsconfig.json
。遵循此做法将使 Turborepo 更轻松地缓存你的类型检查任务,从而简化你的配置。
¥As mentioned in the Structuring your repository guide, you want to treat each package in your tooling as its own unit. This means each package should have its own tsconfig.json
to use instead of referencing a tsconfig.json
in the root of your project. Following this practice will make it easier for Turborepo to cache your type checking tasks, simplifying your configuration.
唯一可能需要在工作区根目录中使用 tsconfig.json
的情况是,需要为不在包中的 TypeScript 文件设置配置。例如,如果你有一个用 TypeScript 编写的脚本需要从根目录运行,则该文件可能需要一个 tsconfig.json
。
¥The only case in which you may want to have a tsconfig.json
in the Workspace root is to set configuration for TypeScript files that are not in packages. For example, if you have a script written with TypeScript that you need to run from the root, you may need a tsconfig.json
for that file.
但是,我们不建议这样做,因为工作区根目录中的任何更改都会导致所有任务缓存丢失。相反,将这些脚本移动到代码库中的其他目录。
¥However, this practice is also discouraged since any changes in the Workspace root will cause all tasks to miss cache. Instead, move those scripts to a different directory in the repository.
你可能不需要 TypeScript 项目引用
¥You likely don't need TypeScript Project References
我们不建议使用 TypeScript 项目引用,因为它们会为你的工作区引入另一个配置点和另一个缓存层。这两种方式都可能在你的仓库中造成问题,而且几乎没有什么好处,所以我们建议在使用 Turborepo 时避免使用它们。
¥We don't recommend using TypeScript Project References as they introduce both another point of configuration as well as another caching layer to your workspace. Both of these can cause problems in your repository with little benefit, so we suggest avoiding them when using Turborepo.
限制
¥Limitations
你的编辑器不会使用包的 TypeScript 版本
¥Your editor won't use a package's TypeScript version
tsserver
无法在你的代码编辑器中为不同的包使用不同的 TypeScript 版本。相反,它会发现一个特定的版本并在任何地方使用它。
¥tsserver
is not able to use different TypeScript versions for different packages in your code editor. Instead, it will discover a specific version and use that everywhere.
这可能会导致编辑器中显示的 linting 错误与你运行 tsc
脚本检查类型时显示的 linting 错误不同。如果这对你来说是一个问题,请考虑使用 保持 TypeScript 依赖在同一版本上。
¥This can result in differences between the linting errors that show in your editor and when you run tsc
scripts to check types. If this is an issue for you, consider keeping the TypeScript dependency on the same version.