Appearance
第 2 章 工作台
📖 工具间的钥匙
"想造信号库?"主编老墨把一把黄铜钥匙放在桌上,"先得有工作台。去工具间看看吧。"
工具间在消息城最老的楼里,门一推开,灰尘在阳光里打转。屋子不大,但三样东西闪闪发光,每样都挂着一块牌子:
- 第一样,一本厚厚的手册,封面写着"我的工具箱清单"。打开一看,里面密密麻麻记着:这个工具有什么用、怎么调用它。
- 第二样,一块工作台面板,上面有好多旋钮和插槽,写着"规则设置"。拧紧哪个旋钮,工作台就更严格。
- 第三样,一个自动检查员,穿着绿红两色的外套。你把东西递给它,它当场检查:"合格!"(亮绿灯)或者"不合格!这里有错!"(亮红灯)。
"这三样宝贝,一样都不能少。"老墨说,"手册叫 package.json,面板叫 tsconfig.json,检查员叫 vitest。"
小铃挠挠头:"那……它们到底是干什么的?"
"干完今天这章,你自己就明白了。开始吧。"
🎯 本章要解决什么
一句话问题:怎么搭一个能写 TypeScript、还能自动检查对错的工作台?
读完这一章,你会知道:
- 三样工具各是干什么的:package.json、tsconfig.json、vitest;
- 怎么写你的第一个 TypeScript 函数;
- 怎么写第一个测试,并看着它亮绿灯。
💡 概念讲解
工具一:package.json(工具箱清单)
上一章你建了 signal-book 文件夹。现在我们要告诉电脑:"这是一个正经的项目,我要往里面装工具。"
怎么告诉它?写一个叫 package.json 的文件——它就是工具箱清单:里面写着项目叫什么名字、装了哪些工具、怎么运行它们。
你不需要背下它的内容。需要的时候,用一条咒语就能生成它:
bash
npm init -ynpm 是工具搬运工:你喊它,它就跑来跑去帮你装工具、管工具。init 意思是"开始一个新项目",-y 意思是"别问那么多问题,直接用默认设置吧"。
工具二:tsconfig.json(规则面板)
上一章我们说过,TypeScript 是 JavaScript 的大哥哥,它会给数据贴类型标签。可是,TS 要怎么知道该严格到什么程度?答案就写在 tsconfig.json 里——它像工作台的规则面板。
书里每一章,我们用的都是同一块面板(内容见"章末完整代码")。它的核心规则是:
json
{
"strict": true
}strict 就是"严格"的意思。把它拧到 true,工作台就会非常较真:类型不对,立刻大喊。严是好事——错误在写代码时就发现,总比程序跑起来才崩好。
工具三:vitest(自动检查员)
最后是今天的主角:vitest。它是一个测试工具——自动检查员。
怎么用?你写一个"检查单"(测试文件),在上面写明:"我觉得这个函数应该返回 6"。然后 vitest 把函数真的跑一遍,对比结果:
- 一样 → 亮绿灯(通过)
- 不一样 → 亮红灯(失败,还会告诉你差在哪)
mermaid
graph LR
src["src/money.ts 📄<br/>你的代码"] --> vitest["vitest 🧪 自动检查员"]
tests["tests/money.spec.ts 📋<br/>你的检查单"] --> vitest
vitest --> ok["绿 ✓ 通过"]
vitest --> bad["红 ✗ 失败,并告诉你差在哪"]为什么测试这么重要?因为接下来 19 章,我们每改一次代码,都可能把前面弄好的东西改坏。有了检查员,每次改完跑一遍 npm test,它替我们盯着——"放心,你改的地方没弄坏别的东西。" 这叫回归测试,以后你会天天听到这个词。
✍️ 动手写代码
开工!这次我们要敲不少命令,别怕,都是套路。
第 1 步:走进项目文件夹
打开终端,走进上一章建的文件夹:
bash
cd signal-book第 2 步:生成工具箱清单
bash
npm init -y🚀 现在跑一下,你应该看到:终端里打印出一个小表格,里面有
name: "signal-book"、version之类的东西。然后文件夹里多了一个package.json文件。
第 3 步:请搬运工装工具
bash
npm install -D typescript vitest-D 的意思是"这两个工具只在开发时用"(以后送给别人玩的时候,不用带上它们)。
🚀 现在跑一下,你应该看到:一堆像下雨一样的文字滚过去,最后出现类似
added 100+ packages的字样。这时文件夹里多了一个node_modules文件夹——这是工具们的仓库,你永远不用管它里面有什么。
第 4 步:在清单里登记"怎么运行测试"
打开 package.json,你会看到 npm install 已经把工具写进清单了(devDependencies 那一段)。现在我们要再加一条:告诉工作台,"运行测试"这个动作叫什么。找到 "scripts" 这一行(现在应该是空的 "scripts": {}),把它改成:
json
"scripts": {
"test": "vitest run"
}改完的 package.json 大概长这样(版本号可能和你的略有不同,没关系):
json
{
"name": "signal-book",
"version": "1.0.0",
"scripts": {
"test": "vitest run"
},
"devDependencies": {
"typescript": "^5.7.3",
"vitest": "^3.0.5"
}
}以后我们只要喊
npm test,工作台就知道:去把检查员叫来,把所有测试跑一遍。
第 5 步:立规则面板
新建一个文件 tsconfig.json,把下面的内容抄进去(这是书里唯一的版本,后面每章都一样):
json
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"noEmit": true,
"skipLibCheck": true
},
"include": ["src", "tests"]
}不用理解每一行,知道
strict: true是"严格模式"就够了。include是说"要检查src和tests两个文件夹里的代码"。
第 6 步:写第一个 TypeScript 函数
新建 src 文件夹,在里面建 money.ts,抄进下面的代码:
ts
// 小铃的赚钱计算:每份报纸赚 2 块钱。
export function money(count: number): number {
return count * 2;
}这是你的第一个 TypeScript 函数!注意两个地方和 JS 不一样:
count: number—— 参数count贴上了"数字"标签;): number—— 返回的东西也要是数字。
第 7 步:写检查单(第一个测试)
新建 tests 文件夹,在里面建 money.spec.ts:
ts
import { describe, expect, test } from 'vitest';
import { money } from '../src/money';
describe('小铃的赚钱计算', () => {
test('送 1 份报纸,赚 2 元', () => {
expect(money(1)).toBe(2);
});
test('送 3 份报纸,赚 6 元', () => {
expect(money(3)).toBe(6);
});
});读一读这张检查单,它很像人话:
describe('小铃的赚钱计算', ...)—— "接下来要检查的主题是:小铃的赚钱计算";test('送 1 份报纸,赚 2 元', ...)—— "有一个测试叫:送 1 份报纸赚 2 元";expect(money(1)).toBe(2)—— "我期望:money(1)的结果等于 2"。
expect 是"期望",toBe 是"等于"。检查员的记事本就是这两句话。
第 8 步:叫检查员来!
回到终端,喊:
bash
npm test🚀 现在跑一下,你应该看到(这就是传说中亮绿灯的时刻):
✓ tests/money.spec.ts (2 tests) Test Files 1 passed (1) Tests 2 passed (2)两个测试全过了!你的工作台搭好了。🎉
🧰 TS 小课堂:第一次正式开张!
今天学三样 TS 语法,都是以后天天用的。
1. 类型标注
给变量或参数贴"类型标签":
ts
let count: number = 1; // count 是数字
let name: string = '小铃'; // name 是文字
let ok: boolean = true; // ok 是"是/否"三种最常见的标签:number(数字)、string(文字)、boolean(是/否)。
如果标签贴错了,比如 let count: number = '三';,工作台会立刻大喊:"这里类型不对!"——这就是严格模式的好处。
2. 函数的"签名"
export function money(count: number): number 的尾巴是函数的签名:它声明了"进门要带什么(参数类型)、出门会交出什么(返回类型)"。以后看书里的库函数,先看签名,就能猜到它怎么用。
3. export 和 import(公告栏)
export—— 把自己的东西摆上公告栏,别人才能拿;import—— 从公告栏取东西。
测试文件第一行 import { money } from '../src/money' 就是在说:"去 src/money 的公告栏上,把 money 拿过来。"(.. 表示"上一级文件夹")
📚 工具箱
下面是本章的三样工具。注意:它们叫"工具",不是消息城术语,所以不进书末尾的正式词典——记住它们的作用就行:
| 工具 | 它是什么 | 一句话记住它 |
|---|---|---|
npm | 工具搬运工 | 帮你装工具、管工具 |
package.json | 工具箱清单 | 写着装了啥、怎么运行 |
tsconfig.json | 规则面板 | 里面 strict: true 就是严格模式 |
node_modules | 工具们的仓库 | 永远不用打开它 |
vitest | 自动检查员 | 跑测试,绿=对,红=错 |
npm test | 召唤检查员的咒语 | 每次改完代码就喊一次 |
📦 章末完整代码
这一章你的 signal-book 文件夹应该长这样:
signal-book/
├── demo/
│ └── ch01.mjs ← 第 1 章的,还在
├── node_modules/ ← 工具仓库,不用管
├── package.json
├── tsconfig.json
├── src/
│ └── money.ts
└── tests/
└── money.spec.tspackage.json 完整内容:
json
{
"name": "signal-book",
"version": "1.0.0",
"scripts": {
"test": "vitest run"
},
"devDependencies": {
"typescript": "^5.7.3",
"vitest": "^3.0.5"
}
}tsconfig.json 完整内容:
json
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"noEmit": true,
"skipLibCheck": true
},
"include": ["src", "tests"]
}src/money.ts 完整内容:
ts
// 小铃的赚钱计算:每份报纸赚 2 块钱。
export function money(count: number): number {
return count * 2;
}tests/money.spec.ts 完整内容:
ts
import { describe, expect, test } from 'vitest';
import { money } from '../src/money';
describe('小铃的赚钱计算', () => {
test('送 1 份报纸,赚 2 元', () => {
expect(money(1)).toBe(2);
});
test('送 3 份报纸,赚 6 元', () => {
expect(money(3)).toBe(6);
});
});✅ 跑通了? 只要
npm test能打出2 passed,工作台就搭好了。从下一章开始,我们真的要开始造信号库了!
🎮 动手试试
怎么玩
先合上答案,自己在本子上写出答案,再点开对照。忍得住才点开哦!
1. 预言输出(猜一猜)
小铃在 money.spec.ts 里加了一个测试:
ts
test('送 10 份报纸', () => {
expect(money(10)).toBe(20);
});猜猜看:跑 npm test 会亮绿还是红?
再猜一个:let count: number = '三'; 这一行,工作台会大喊吗?
👉 点开看答案
第一题:绿。money(10) 等于 10 × 2 = 20,检查员说"对!"。
第二题:会大喊。'三' 是文字(string),却贴了数字(number)的标签,严格模式立刻报错。类型标签不是装饰品,是工作台的规矩。
2. 帮小铃找 bug(抓错)
小铃想给 money 写个测试,可它总是红灯:
ts
test('送 2 份报纸', () => {
expect(money(2)).toBe(6);
});是 money 函数错了,还是小铃的期望写错了?
👉 点开看答案
是期望写错了。money(2) 是 2 × 2 = 4,不是 6。小铃的检查单写错了,函数没错。改成 toBe(4) 就绿了。
红灯不可怕,它是在说"你的检查单和代码,有一个错了"——检查员比我们诚实。
3. 填空(补全)
小铃要给蛋糕店写个函数 cake:每个蛋糕 5 块钱。补全下面函数的签名:
ts
export function cake(count /* 这里少了点什么? */) /* 这里也少了点什么? */ {
return count * 5;
}👉 点开看答案
两处都补 : number:
ts
export function cake(count: number): number {
return count * 5;
}(如果写完想验证,再补一个测试:expect(cake(2)).toBe(10);)
4. 小挑战(改代码)
主编宣布:"从明天起,每份报纸赚 3 块钱!"
小铃改完 src/money.ts 里的 return count * 2 变成 return count * 3,跑 npm test——红了!
这是为什么?小铃应该怎么办?
👉 点开看答案
红是因为检查单还是旧的:money.spec.ts 里写着"送 3 份赚 6 元",可函数现在返回 9 元,检查员当然喊红。
这是测试存在的意义:当代码行为改变时,它会提醒你"检查单也要跟着改"。把 money.spec.ts 里的期望改成新价格(送 1 份赚 3 元、送 3 份赚 9 元),再跑就绿了。
以后每章我们改代码,都要这样:改代码 → 跑测试 → 绿了才放心。
🏁 本章小结
- package.json 是工具箱清单,tsconfig.json 是规则面板,vitest 是自动检查员;
- 测试就是你写的检查单:
expect(结果).toBe(期望),绿=对,红=错; - 从今往后,每次改完代码都要跑
npm test——检查员会替我们盯住所有旧功能。
下一章,正式开工造信号库的第一个零件:信号!