TypeScript 学习路线 MOC

从会写 JavaScript 到能用 TypeScript 设计可靠业务契约的七阶段学习路线,覆盖类型心智、收窄、泛型、运行时边界、React 与工程化。

#type / moc #status / growing #tech / dev #resource / typescript

[!info] related notes

TypeScript 学习路线 MOC

这条路线解决什么问题

TypeScript 的难点不是给变量补 string,而是学会把“不可能状态”排除在业务代码之外。本路线面向已经熟悉常用 JavaScript 写法、但还没有形成类型设计心智的人。

[!abstract] 路线结论 先分清 JavaScript 运行时和 TypeScript 编译期,再掌握推断、对象类型、联合与收窄;随后用可辨识联合和泛型表达业务关系,并学习外部数据必须运行时校验。最后进入 React、跨端契约、tsconfig 和 monorepo。

针对已有 JS 基础的使用方式

当前情况建议
熟悉数组方法、函数和接口写法快速通过阶段一,但完成每个“完成标准”
经常使用 as 解决报错重点学习阶段二、三和五
会写 React 组件阶段三后进入阶段六,同时继续阶段四、五
只会看类型,不会设计类型从 BodySense StreamEvent 契约开始反向阅读
被 tsconfig、编辑器红线困扰完成语言主线后再进阶段七

难度标记

  • L1 入门 · L2 基础巩固 · L3 核心类型设计 · L4 工程/跨端 · L5 编译器与进阶
  • 源码:否 / 建议 / 需要 —— 是否值得对照 TypeScript Handbook、编译器实现或项目真实源码

依赖关系

flowchart TD
    S1["阶段一 编译期心智"] --> S2["阶段二 对象与组合类型"]
    S2 --> S3["阶段三 收窄与状态建模"]
    S3 --> S4["阶段四 泛型与类型变换"]
    S3 --> S5["阶段五 运行时边界"]
    S4 --> S6["阶段六 React 与业务契约"]
    S5 --> S6
    S6 --> S7["阶段七 工具链与大型工程"]

阶段一:建立编译期类型心智

目标:知道 TypeScript 能保证什么、不能保证什么;优先依赖推断而不是到处手写类型。

完成标准

  • 能解释类型擦除和 JavaScript 运行时的关系
  • 能区分注解、推断和断言
  • 能说明 anyunknownnevervoid 的职责
序号笔记核心问题难度源码
1.1TypeScriptTypeScript 在工具链中的位置L1
1.2TypeScript 类型推断与类型标注何时让编译器推断,何时显式标注L2
1.3TypeScript 中的 unknown 与 any安全未知值与放弃检查的差异L2
1.4TypeScript 静态类型与运行时校验类型为什么不能验证网络数据L3建议
1.5TypeScript 速记高频类型与工具类型快速入口L1

阶段二:对象与组合类型

目标:用对象类型、联合、交叉、可选属性与索引访问准确表达数据形状。

完成标准

  • 能在 typeinterface 间按能力而非口号选择
  • 能解释可选属性与 undefined 的差异
  • 能读懂 T[K]keyof TRecord<K, V>
序号笔记核心问题难度源码
2.1TypeScript 对象类型、type 与 interface如何描述和组合对象形状L2
2.2TypeScript 中的 strictNullChecks空值如何进入类型系统L2
2.3TypeScript 中的 exactOptionalPropertyTypes缺失属性与显式 undefined 的边界L3
2.4TypeScript 中的 noUncheckedIndexedAccess索引读取为什么可能不存在L3
2.5TypeScript 工具类型示例Partial/Pick/Omit/Record 如何变换对象L2

阶段三:收窄与业务状态建模

目标:让控制流帮助编译器排除不可能状态,而不是用断言压掉错误。

完成标准

  • 能用 typeofin、判空和类型谓词收窄 unknown
  • 能用共同判别字段设计业务状态
  • 能用 never 做穷尽检查
序号笔记核心问题难度源码
3.1TypeScript 联合类型、收窄与类型守卫控制流如何缩小类型范围L3建议
3.2TypeScript 可辨识联合与穷尽检查如何把业务状态设计为有限集合L3建议
3.3TypeScript 的 as const、satisfies 与类型断言保留字面量信息而不欺骗编译器L3建议
3.4TypeScript 中的 useUnknownInCatchVariablescatch 中为什么应先确认错误形状L2

阶段四:泛型与类型变换

目标:表达输入和输出之间的关系,而不是把泛型当作“任意类型占位符”。

完成标准

  • 能写带约束的泛型函数
  • 能解释 keyof、索引访问与映射类型如何协作
  • 能读懂基础条件类型与 infer
序号笔记核心问题难度源码
4.1TypeScript 泛型、keyof 与索引访问如何表达参数之间的类型关系L3建议
4.2TypeScript 高级类型条件类型、映射类型与 infer 总览L4建议
4.3TypeScript 中的 strictFunctionTypes函数参数兼容性为何特殊L4建议
4.4TypeScript 结构化类型与函数兼容性“形状兼容”如何影响赋值和回调L4建议

阶段五:运行时边界与模块

目标:把 API、JSON、localStorage、环境变量等外部输入视为不可信数据。

完成标准

  • 能从 unknown 开始解析外部数据
  • 能说明类型断言和运行时校验的根本差异
  • 能区分类型导入与运行时导入
序号笔记核心问题难度源码
5.1TypeScript 静态类型与运行时校验网络边界如何建立可信类型L3建议
5.2Zod 运行时 Schema 校验Schema 如何把 unknown 解析为可信输出L3建议
5.3TypeScript 中的 import type 与普通 import类型依赖是否进入运行时L2
5.4TypeScript 中的 .d.ts 声明文件没有源码的库如何提供类型L3
5.5TypeScript 中的全局声明与全局扩展全局类型如何安全扩展L4

阶段六:React 与真实业务契约

目标:在组件、Hooks、Reducer、Context 和跨端事件中设计稳定类型。

完成标准

  • 能正确标注 props、children、事件与 ref
  • 能用可辨识联合设计 reducer action
  • 能解释服务端数据为什么仍要运行时校验
序号笔记核心问题难度源码
6.1React 中的 TypeScript 组件与 Hook 类型React 边界如何保留推断L3建议
6.2React 类型化包装组件与多态组件如何继承原生或第三方组件 props 并保留 refL3建议
6.3useReduceraction 联合如何驱动状态机L3建议
6.4Context 与状态管理边界Context 值和 action 如何设计L3建议
6.5前后端 DTO 同步跨端契约如何避免漂移L4建议
6.6BodySense MOC在真实三语言契约中练习L4需要

阶段七:工具链与大型工程

目标:理解一个 TypeScript program 如何被编辑器、编译器、bundler 和 monorepo 工具共同处理。

完成标准

  • 能分清 tsc、tsserver、ESLint 与 bundler
  • 能解释 modulemoduleResolution
  • 能读懂项目引用与 monorepo 类型边界
序号笔记核心问题难度源码
7.1TypeScript、tsc、tsconfig 与 tsserver 的关系四个工具层如何协作L3
7.2tsconfig 使用详解program 边界和检查规则在哪里定义L3
7.3module 与 moduleResolution 的关系输出格式与查找算法如何分工L4建议
7.4TypeScript 中的 nodenext 与 bundler不同宿主如何选解析策略L4
7.5TypeScript 中的 references大型项目如何分割构建图L4
7.6TypeScript Monorepo 中源码引用与构建引用源码消费和构建产物如何选择L5建议

如果只抓主干,优先这 8 个主题

  1. 类型推断与标注
  2. 对象类型、type 与 interface
  3. unknown 与 any
  4. 联合与收窄
  5. 可辨识联合与穷尽检查
  6. 泛型、keyof 与索引访问
  7. as const、satisfies 与断言
  8. 静态类型与运行时校验

0 到 1 的完成标准

  • 能在不使用 any 和不滥用 as 的情况下解析一个外部 JSON
  • 能用可辨识联合表达 loading/success/error 或事件状态
  • 能给对象访问辅助函数写出 K extends keyof T
  • 能解释类型为什么在运行时不存在
  • 能为 React reducer 设计 action 联合并做穷尽检查
  • 能读懂 BodySense StreamEventBase 的三个泛型参数
  • 能定位一次报错来自类型系统、tsconfig、编辑器还是 bundler

第一条项目练习路径

  1. 阅读 BodySense packages/contracts/src/stream-events.ts
  2. 找出字面量类型、泛型、unknownnever 和可辨识联合。
  3. 阅读前端 activeTurnReducer.ts,观察 event.type 如何收窄。
  4. 找出 consultationService.ts 中从 JSON 直接断言为 StreamEvent 的位置。
  5. 为该边界设计运行时解析器和失败测试。
创建于 2026/7/29 更新于 2026/8/1