每日一报
Something About Typescript
extends
Related Material
Proposal for merging array or object options in tsconfig file
在当前的 typescript
实现中,配置继承采用了 替换而非递归合并 的策略。
tsconfig.json
的 extends
机制只会在子配置中 覆盖 基配置的同名字段,而不会对 数组 或 嵌套对象 做 增量合并。也就是说,只要在 子配置中定义 了某个字段(例如 compilerOptions.paths
),就会 完全替换 基配置里的对应映射,除非根本 不在子配置 中出现,该字段才会被 完整继承。
references
extends
机制 不会继承 基配置里的 references
字段。是唯一一个被 排除 在继承之外的顶层属性。如果子配置中没有显式声明 references
,那么基配置里的项目引用将不会出现在最终的配置中。
在 Proposal for merging array or object options in tsconfig file 提案中,建议在子配置中声明一个顶层数组 merge
,列出需要合并而非覆盖的字段,适用可合并配置项如下:
compilerOptions
下的paths
、lib
、typeRoots
、rootDirs
、moduleSuffixes
等。watchOptions
下可合并的列表。顶层字段
files
、include
、exclude
(基于进一步讨论也可能纳入)。references
虽为对象,但目前提案中未默认合并。
typescript
在解析时会先读取基配置,再将子配置中对应字段 深度合并。
TypeScript Project References: 优化大型项目的类型系统
良好的架构设计本身就是提高系统质量和开发效率的关键因素。
typescript
的 references
是一种强大的项目组织机制,它通过声明式的方式向 typescript
编译器传达子项目间的依赖关系图(抽象解释为 架构图),而非像 extends
那样提供配置继承功能。这一特性专为优化大型 typescript
项目(如 monorepo
架构)的开发和编译体验而设计。
核心价值:双重性能优化
references
带来了两方面的性能提升:
首先,它实现了增量编译,显著加快构建速度。当修改某个模块时,typescript
只需重新编译该模块及其直接依赖项,而非整个项目。这在大型代码库中尤为重要,可将编译时间从分钟级缩短至秒级。
其次,它通过 局部类型检查 提升了开发阶段的编辑器响应速度。IDE
不再需要加载整个项目的类型定义,而是根据明确的依赖关系只加载相关模块的类型信息,使得代码补全、错误提示等功能反应更加迅速。
在现代前端工程中的应用
在现代前端开发中,实际的代码 转译工作 通常由 webpack
、rollup
、vite
等打包工具处理,而 typescript
主要负责 类型检查。当开发者修改某个模块时,IDE
需要判断这些更改对当前模块及相关模块类型系统的影响。
而在大型项目中,模块间的依赖关系错综复杂。references
通过明确定义模块边界,告知 typescript
和 IDE
:当某个模块发生变更时,只需在特定的模块集合中分析类型变化,而无需处理整个项目的类型上下文。这种精确的作用域限定使得 IDE
能够提供更快速的类型反馈,极大提升了开发体验。
架构设计最佳实践
设计
references
本质上也是对项目架构的直接表达和强化,明确依赖关系,实现了关注点分离的架构原则,强制开发者遵循预定的架构边界,确保不同模块的责任边界清晰,防止架构随时间推移而被无意破坏。
设计 references
结构时,应遵循 自下而上 的方法:首先识别不依赖其他模块的基础层,然后构建依赖基础层的中间层,最后配置依赖中间层的应用层。这确保了依赖关系保持 单向流动,避免了循环依赖带来的复杂性。
对于大型、复杂的 typescript
项目,references
不仅是性能优化工具,更是架构清晰度的保障。它强制开发团队思考和明确模块间的边界与关系,使代码库结构更加合理,便于团队协作开发和长期维护。
references
不能简单按照已存在项目的依赖关系,借助工具全量扫描来自动生成架构图,作为当前项目的 references
配置,这会存在一些问题:
- 依赖关系不明确,模块间存在模糊的依赖关系。
- 忽略潜在的滥用问题。
因此开发者可以借助自动生成的架构图来反思当前项目的架构是否合理,借此辅助配置 references
,而不能直接将自动生成的架构图作为 references
配置。