Skip to content

第 1 周 · Day 7:周复盘方法论——把一周所学变成自己的 ​

手册任务:周复盘 + 整理。用 Excalidraw 画 monorepo 结构图,写 300 字周记,当日产出:架构图 + 周记。 本篇解决的问题只有一个:怎么确认这六天学的东西真的进了脑子,而不是"看过一遍"。

今日目标 ​

  1. 不看教程画出本周 monorepo 项目结构图,导出 PNG 存档
  2. 按四段模板写一篇 300 字周记
  3. 过一遍 10 题自检清单,答不上来的标记出来,回读对应 Day 的教程

概念讲解:为什么复盘比再学一天新东西更值钱 ​

先说一个扎心的数字。艾宾浩斯遗忘曲线的结论:学完不复习,一周后记忆只剩 25% 左右。你现在觉得"泛型、条件类型、monorepo 我都懂了",这个判断基本不可信,因为它的依据是"我看懂了教程"。而"看懂"是全世界最容易骗自己的事。

为什么?因为识别和提取是两回事。教程摆在面前,你认得每一行代码,这叫识别,几乎不费脑子。合上教程,让你自己把 DeepPartial 写出来,这叫提取,费脑子,而且是真会了的唯一证据。你那点"都会了"的感觉,多半是识别系统在骗你。

所以检验标准只有一个:不看资料,能不能复述、能不能重做。讲不出来、写不出来的,就是不会,不管当时看教程多顺。

由此推出本篇的核心:复盘不是重读笔记。重读笔记还是在做识别,舒服,且无效。有效的复盘是输出倒逼输入,用三种输出把知识从"认得"逼到"说得出、写得出":

输出方式逼出什么对应今天的产出
画图结构是否在脑中成形monorepo 架构图
写作概念是否真的理解300 字周记
自测细节是否记牢10 题自检清单

这套流程后面 22 周照用

今天是第 1 周的 Day 7,也是以后所有 Day 7 的模板。每个复盘日都走这套流程:画当周主题的结构图,写四段周记,做 10 题自检,整理 git。变的只是内容,方法不动。

核心知识 ​

1. 架构图复盘法 ​

为什么是画图?一张图画得出来,说明各部分的关系在你脑中是连着的;画不出来,说明你记住的只是一堆散点。"结构"这个词的重点在关系:谁依赖谁、谁先谁后。文字笔记擅长记细节,图擅长记关系,两者互相替代不了。

工具选 Excalidraw:excalidraw.com 打开就能画,不用注册不用安装。它的特点是手绘风,歪歪扭扭是特色。这份"不精致"恰好是优点,提醒你别在美观上花时间。10 分钟画完一张,够用就好。

一张合格的 monorepo 结构图应该画什么?给你一份文字版清单,照着画:

text
节点(3 个,方框表示):
  ① 根节点:monorepo 根,画在中间或顶上
  ② apps/web:应用包,React 页面
  ③ packages/shared:共享包,类型和工具函数

边(1 条,带箭头):
  apps/web → packages/shared
  箭头上标注依赖协议:workspace:*

职责标注(3 处,写在图旁边):
  pnpm:管依赖安装,pnpm-workspace.yaml 圈定哪些目录是包
  turbo:管任务编排和缓存,turbo.json 声明任务依赖
  tsc:管 shared 包构建,源码编译成 dist

缓存标注(1 处):
  .turbo/ 目录:turbo 缓存的落地处,命中缓存则任务直接跳过

画的时候心里要有三个层次:节点是包,边是依赖,标注是职责。少了箭头上的 workspace:*,这张图就只是目录树;少了职责标注,看图的人不知道 pnpm、turbo、tsc 各管哪一段。

画不出来也别对着教程抄

先凭记忆画,卡住了再翻 Day 4-6 的教程确认,然后合上继续画。对着教程抄出来的图没有复盘效果,识别和提取的区别就在这。

画完导出 PNG(左上角菜单,Export),存到笔记目录,文件名带上周数,比如 week01-monorepo.png。.excalidraw 源文件也一起留着,第 2 周往里加新包时,先改这张图再动手。

2. 300 字周记模板 ​

先分清:周记不是日记。日记记感受,周记记认知变化。固定四段,每段一两句话,总共 300 字上下:

  1. 本周最大的收获:用自己的话说,禁止抄教程原句,抄得出来说明没消化
  2. 卡得最久的一个问题:以及怎么解决的。这段最值钱,下周大概率还会撞上同类问题
  3. 还含糊的概念:诚实列出来。写这段不丢人,它是下周的输入
  4. 下周开始前要补什么:给未来的自己留具体动作,能执行的那种,别写"多练习"这种空话

第 1 周示例,照这个密度写:

text
① 本周最大收获:泛型不是语法炫技,是把类型当参数传,一份代码适配
多种类型还不丢检查。DeepPartial 一递归,配置合并的类型立刻就顺了。
② 卡得最久:apps/web 引 workspace:* 报"找不到包",查了半小时,最后
发现是 shared 的 package.json 里 name 和引用名不一致,改名后一条命
令就通。
③ 还含糊:条件类型里的 infer 能看懂但不敢自己写;映射类型的 as 重
映射同理。
④ 下周前补:把 Day 2 的条件类型例子脱稿敲一遍,敲不出来就重读。

300 字是刻意的限制,逼你取舍。写得下"最大收获",写不下"所有收获",你就必须想清楚哪个才是最大。

3. 第 1 周知识自检清单 ​

规则:每题先自己口头回答,说完整了再点开答案对照。口头说不出来的就记下题号,回读对应 Day 的教程。

问题 1:泛型和 any 都能接受任意类型,本质区别是什么?(Day 1)

答案

any 是放弃类型检查,传什么进去、之后怎么用,编译器全不管。泛型是把类型当参数,调用时确定具体类型,之后全程保留检查。一个丢类型信息,一个保类型信息。

问题 2:<T extends { id: number }> 这种约束是干嘛的?什么时候必须加?(Day 1)

答案

给泛型参数划范围,保证 T 至少具备某些属性。要在函数里访问传入值的特定属性(比如 obj.id)时必须加约束,否则编译器不知道 T 上有没有这个属性,会直接报错。

问题 3:条件类型是什么?举一个你这周见过的例子。(Day 2)

答案

类型层面的三元表达式:T extends U ? X : Y,满足条件取 X,否则取 Y。例如 NonNullable<T> = T extends null | undefined ? never : T。

问题 4:映射类型里 keyof 和 as 各起什么作用?(Day 2)

答案

keyof T 取出键的联合类型,作为遍历的对象;as 是重映射,可以改键名(比如把 name 变成 getName),也可以写 as never 把某个键从结果里过滤掉。

问题 5:Partial<T> 只把第一层变可选,DeepPartial 为什么要用递归?(Day 2)

答案

Partial 只处理对象第一层的属性,嵌套对象还是原样。DeepPartial 对每个属性的值做判断:还是对象就递归处理,这样任意层级都变可选。深度合并配置、局部更新大对象时靠它。

问题 6:类型守卫里 pet is Fish 和普通 boolean 返回值差在哪?(Day 3)

答案

返回 pet is Fish 后,在函数返回 true 的分支里,编译器会把 pet 收窄成 Fish,后续属性访问都有检查。返回普通 boolean,编译器只知道真假,类型不收窄。前者是运行时检查加编译期收窄的组合。

问题 7:unknown 和 any 差在哪?什么时候该用 unknown?(Day 3)

答案

any 是双向放弃:什么都能赋给它,它也什么都能干。unknown 是单向限制:什么都能赋给它,但它不能直接用,必须先收窄(类型守卫或断言)才能操作。接外部数据(接口返回、JSON.parse 结果)时用 unknown,逼你先校验再使用。

问题 8:workspace:* 和 ^1.0.0 有什么区别?前者解决了什么问题?(Day 4)

答案

^1.0.0 指向 npm 仓库里的某个版本;workspace:* 指向本仓库内的包,pnpm 安装时直接软链到本地源码,发布时再自动替换成真实版本号。它解决了本地包改动要发版或手动 link 才能生效的问题,改完立即生效。

问题 9:turbo 任务里的 ^build 是什么意思?和直接写 build 差在哪?(Day 5)

答案

^build 表示先把这个包依赖的其它包的 build 全部跑完,再跑自己的。直接写 build 只跑自己的,依赖包可能是旧产物。这种依赖关系在 turbo.json 里声明,turbo 自动按拓扑顺序调度,还能并行。

问题 10:packages/shared 的 exports 字段里,types 为什么必须放最前面?(Day 6)

答案

exports 对象按声明顺序匹配。TypeScript 在 node16、nodenext 解析模式下,匹配到 main 或 import 指向的 JS 后就不再找类型了,所以同一入口的 types 条件必须写在最前面,否则 TS 报找不到类型声明。

10 题全对也别飘

全对说明第 1 周及格,不说明可以跳过复盘。图、周记、git 整理三件事做完,本周才算收口。

动手任务:完成本周复盘 ​

按顺序做完五步,预计 60 到 90 分钟。

第一步:画 monorepo 结构图(20 分钟)

关掉教程,打开 excalidraw.com,对照上面的文字版清单凭记忆画:三个节点、一条带 workspace:* 标注的依赖边、三处职责标注、一处缓存标注。卡住的地方翻 Day 4-6 教程确认,合上继续。

第二步:导出存档(5 分钟)

菜单点 Export 导出 PNG,存到笔记目录,命名 week01-monorepo.png。源文件也留着,下周改图用。

第三步:写 300 字周记(20 分钟)

按四段模板写,对照示例的密度。写"还含糊"那段时别敷衍,它就是你下周的补课清单。

第四步:做自检清单(15 分钟)

10 题逐个口头回答。答不上来的记下题号和对应的 Day,回读该 Day 教程的对应小节。回读也算复盘的一部分,不丢人。

第五步:git 提交整理(15 分钟)

本周代码如果提交得零散,不要去改历史,rebase 重写历史的收益远小于风险。收尾做两件事:未提交的内容分开提交,然后打一个 tag。

bash
# 未提交的内容按类型分开:
git add packages/shared
git commit -m "feat(shared): 补充类型导出"
git add apps/web
git commit -m "feat(web): 页面接入 shared 包"

# 打标签收口:
git tag week01-done

commit 划分拿不准时记一个原则就够:一个提交只做一件事。代码一个提交,配置(turbo.json、pnpm-workspace.yaml)一个,文档(周记、架构图)一个。

常见踩坑 ​

复盘变成重读教程。 把 Day 1-6 又刷了一遍,眼睛过了,手没动。没有输出等于没复盘,判断标准就一条:合上资料,图画得出、题答得出。

架构图画成美术作品。 对齐、配色、换字体折腾一下午,结构反而没想清楚。Excalidraw 的手绘风就是防这个的,10 分钟草稿,能看清节点和箭头就行。检验标准:别人看图 30 秒内能说出谁依赖谁。

周记写成流水账。 "周一学了泛型,周二学了条件类型",这是目录不是周记。四段模板缺一不可,尤其第三段"还含糊的",写不出这段多半是在回避,而它恰恰最值钱。

自检先看答案。 题目还没想就点开答案,一看"哦这个我知道"。认得答案和说得出来之间隔着一条鸿沟,先口头回答再对照,顺序不能反。

延伸阅读 ​

  • Excalidraw 官网:打开就能用,画完记得同时保存源文件
  • 费曼技巧(Feynman Technique):本篇周记"用自己的话"那段的理论靠山。核心一句话:能把概念讲到外行听懂,才是真懂。想深入可以搜 "Feynman Technique",fs.blog 上那篇经典文章值得读

下周开始前,把周记第四段留的补课动作清掉。第 1 周到此收口。