← FC Coder · HomePhase 02 · Lesson 20 · 60 min
Lesson20
Phase Two · Fantasy Builder · Matchday 20 · Add the Rules
TS interface Player
给数据加角色
Today's 3 Jobs · 今天这三件事
- 01新建 lib/types.ts 写 export interface Player5 字段球员档案模板
- 02PlayerCard / sandbox 用 Player 类型: Player 注解
- 03🌟 Cursor 弹自动补全 + 拼错红线代码会自己说话
Phase 0-19 你用的是 JS · 宽松 · 错了运行时才发现。今天 TypeScript 进场 —— JS + 类型注解。`interface Player` = 球员档案的模板 · 5 字段必须有 · Cursor 看到 player 自动列字段 · 拼错立刻红线。代码会自己说话。
Essence · 顺嘴本质点
类型 = 数据的角色
Phase 1 #13 player 是档案 · 今天 Player 是档案的模板。
export interface Player {
name: string;
rating: number;
position: string;
nationality: string;
club: string;
}
name: string;
rating: number;
position: string;
nationality: string;
club: string;
}
5 字段
name / rating / position / nationality / club
类型
string / number
用
({ player }: { player: Player })
import type 只导入类型 · 不打包到运行时。现代 TS 共识。
Essence · TS 给的礼物
自动补全 + 拼错抓得到
player. 弹 5 字段 · player.fame 红线 · 编辑器层面就抓。
player. → name / rating / position / nationality / club
player.fame → ⚠️ Property 'fame' does not exist
player.fame → ⚠️ Property 'fame' does not exist
JS · 宽松
写啥都能跑 · 拼错运行时才发现
TS · 加规矩
Cursor 弹候选 · 拼错立刻红线
成本
多写几个 : 类型注解
Cursor IntelliSense 给的"自动补全"力量来自 TS,不是 LLM。这个用 OK。
Roster · 今天 3 个新工具
interface · 注解 · import type
抄着用 · 看 Cursor 自动补全是今天的「哇」。
- 01interface Player { name: string; ... }数据角色模板 —— 任何 Player 必须 5 字段 · 类型正确。export 给全项目用。首字母大写约定。
- 02({ player }: { player: Player })类型注解 —— 告诉 Cursor 参数是什么类型。注解后 · Cursor 看 player.* 自动列字段。
- 03import type { Player } from '@/lib/types'type-only 导入 —— 只导入类型 · 不打包到运行时。现代 TS 共识 · 性能稍好。抄着用。
Half 2 · 在屏幕上
造类型 · 用类型 · 看 Cursor 变聪明
做完一步就点 ✓。Step 6 弹补全那一下是今天的「哇」。
01造类型 · lib/types.ts
01Min
Cursor + pnpm dev
老三件套。
02Min
lib/ 右键 New File · types.ts
新文件 · 空白。
03Min
写 export interface Player { name: string; rating: number; ... }
5 字段 · 每个加类型。name: string / rating: number / position: string / nationality: string / club: string。保存。
02PlayerCard / sandbox 用 Player
04Min
PlayerCard 顶部 import type { Player } · 删 PlayerLike
import type { Player } from '@/lib/types'; 然后 function PlayerCard({ player }: { player: Player }) { ... }。保存。
05Min
回 sandbox · 22 张卡正常 · 无报错
Cursor 看 .map(p => <PlayerCard player={p} />) 时知道 p 是 Player。
03🌟 Cursor 弹补全 + 抓拼错
06Min
🌟 sandbox 写 const haaland = players[0]; haaland.
停在 . 后面 · Cursor 弹 5 个候选 name / rating / position / nationality / club。这是 TS 给的力量。
07Min
故意写 haaland.fame · 看 Cursor 红线
Property 'fame' does not exist on type 'Player'. 编辑器抓错 · 不用跑代码。
08Min
鼠标停在 haaland 看类型推断
弹小框 · 显示 const haaland: Player · TS 自动推断。
04玩 · 加可选字段 · 截图
09Min
新建 lib/players.ts · 强类型 players + byRating
import playersData from ...; import type { Player } from './types'; export const players: Player[] = playersData as Player[]; export function byRating(min: number): Player[] { return players.filter(p => p.rating >= min); }
10Min
sandbox import { players, byRating } from '@/lib/players'
代替之前的 import players from '@/app/data/players.json'。现在每个 player 都是 Player 类型 · 字段补全更准。
11Min
试加可选字段 face?: string
lib/types.ts: interface Player { ... face?: string } · ? 表示可选。Cursor 仍允许 player.face 但提示「可能 undefined」。今天感受一下。
12Min
📸 截图战利品
Mac Shift + Cmd + 4 框 Cursor 弹补全那一刻。存 2026-XX-XX-我的第一个interface.png · Phase 2 第五张战利品。
Half Time · 中场 · 讲给爸爸听
4 题 · 重点:TS 比 JS 早抓错
第 4 题让他讲为什么早抓比晚抓好。
01什么是 TypeScript?和 JS 差在哪?用「宽松 vs 加规矩」讲。Hint ↓
TS = JS + 类型注解。编辑器层面就抓错 · 不用等运行。
02interface Player { name: string; ... } 是什么?用「档案模板」比喻。Hint ↓
任何 Player 角色 · 必须 5 字段 · 类型正确。Phase 1 #13 player 是档案 · 今天 Player 是档案的模板。
03Cursor 看到 player. 弹 5 个候选 —— 为什么 TS 比 JS 准?Hint ↓
TS 知道 player 类型,知道有哪些字段。JS 啥都不知道,只能猜。
04player.fame 拼错时 TS 立刻红线。JS 时代什么时候发现?Hint ↓
JS 要等运行才发现(undefined → 卡上空白 / NaN)。TS 编辑时就抓。早抓比晚抓好 10 倍。
Player Rating · 本课温度计
给「Cursor 变聪明」打个分
说真话。爸爸会看到。
今天难度Difficulty
0
今天开心Fun
0
Final Whistle · 终场哨
你的代码有规矩了 —— Cursor 变成了聪明的同事。
还有 12 步没打勾。Step 6 弹补全那一下今天就过 —— 其他下次补。