一、为什么是 TypeScript
JavaScript 的痛点:
1 2 3
| function getName(user) { return user.profile.name; }
|
代码上线,用户访问,崩了。
TypeScript 把类型信息加进去,编译期就能发现:
1 2 3 4 5 6
| interface User { profile?: { name: string }; } function getName(user: User) { return user.profile.name; }
|
这就是 TypeScript 的核心价值 —— 可信的代码 + 重构友好。
几乎所有主流前端项目(React、Vue 3、Angular、Next.js)都默认或推荐 TypeScript。
二、安装与编译
1 2 3 4 5
| npm install -g typescript tsc --init tsc app.ts tsc tsc --watch
|
实际项目通常用 tsx / ts-node / bun / Vite 直接跑 TS,不用先编译。
三、类型系统速览
基础类型
1 2 3 4 5 6 7 8 9
| let s: string = "hi"; let n: number = 42; let b: boolean = true; let arr: number[] = [1, 2, 3]; let tuple: [string, number] = ["age", 18]; let any_: any; let unknown_: unknown; let nothing: void; let never_: never;
|
Interface vs Type
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| interface User { id: number; name: string; email?: string; readonly created: Date; }
type User2 = { id: number; name: string; };
type Status = 'pending' | 'done' | 'failed'; type WithTime<T> = T & { time: Date };
|
泛型
1 2 3 4 5 6 7 8 9 10 11
| function first<T>(arr: T[]): T | undefined { return arr[0]; }
const n = first([1, 2, 3]); const s = first(['a', 'b']);
function pluck<T, K extends keyof T>(obj: T, key: K): T[K] { return obj[key]; }
|
工具类型(内置)
1 2 3 4 5 6 7 8 9 10
| type User = { id: number; name: string; email: string };
Partial<User> Required<User> Readonly<User> Pick<User, 'id'|'name'> Omit<User, 'email'> Record<string, User> ReturnType<typeof fn> Awaited<Promise<User>>
|
四、类型收窄(Narrowing)
TypeScript 的类型推导很强大,配合判断会自动收窄:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| function format(x: string | number): string { if (typeof x === 'string') { return x.toUpperCase(); } return x.toFixed(2); }
type Cat = { meow(): void }; type Dog = { bark(): void }; function speak(a: Cat | Dog) { if ('meow' in a) a.meow(); else a.bark(); }
function isUser(x: any): x is User { return x && typeof x.id === 'number'; }
|
五、tsconfig.json 关键配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| { "compilerOptions": { "target": "ES2022", "module": "ESNext", "moduleResolution": "Bundler", "strict": true, "noImplicitAny": true, "strictNullChecks": true, "noUnusedLocals": true, "noUnusedParameters": true, "esModuleInterop": true, "skipLibCheck": true, "resolveJsonModule": true, "outDir": "./dist", "sourceMap": true }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"] }
|
strict: true 一定要开 —— 没开等于一半的 TS 价值丢了。
六、踩坑笔记
| 坑 | 现象 | 解法 |
|---|
| any 泛滥 | 类型形同虚设 | 开 noImplicitAny、strict;any 用 unknown 替代 |
| as 强转后崩 | as User 后访问字段 undefined | 别用 as 绕过编译错误,用类型守卫 |
| 第三方库无类型 | Cannot find module 'x' | npm i -D @types/xxx;没有就写 *.d.ts 声明 |
| enum 编译产物大 | bundle 增加几 KB | 用 as const + union 替代 |
| 装饰器报错 | “Experimental support” | tsconfig 开 experimentalDecorators: true |
| 路径别名不生效 | import '@/x' 编译后还是 @/x | tsc 不改导入;用 tsc-alias 或交给 webpack/vite 处理 |
七、推荐组合
| 场景 | 工具链 |
|---|
| 前端框架 | Vite + TypeScript + React/Vue |
| Node 服务 | tsx + TypeScript(开发)+ tsc 编译(部署) |
| 库开发 | tsup / unbuild / rollup-plugin-typescript2 |
| Monorepo | pnpm + TypeScript Project References |
参考