JavaScript 是一门动态类型语言,变量可以随时改变类型。这种灵活性在小型项目中很方便,但随着代码规模增长,类型相关的 bug 会越来越多。TypeScript 就是为解决这个问题而生的。
🎯 为什么需要 TypeScript#
先看一个 JavaScript 中常见的问题:
// 一个看起来正常的函数function calculatePrice(price, quantity) { return price * quantity}
// 调用时传错了参数类型const total = calculatePrice('100', 2)console.log(total) // '100100',不是 200!
// 更隐蔽的错误const user = { name: '张三', age: 25 }console.log(user.adress) // undefined,拼错了 address这些错误在运行时才会暴露,有时甚至很难发现。TypeScript 能在编写代码时就捕获这些问题:
// TypeScript 5.xfunction calculatePrice(price: number, quantity: number): number { return price * quantity}
// ❌ 编译错误:类型"string"的参数不能赋给类型"number"的参数const total = calculatePrice('100', 2)
interface User { name: string age: number address?: string}
const user: User = { name: '张三', age: 25 }// ❌ 编译错误:属性"adress"在类型"User"上不存在。你是否指的是"address"?console.log(user.adress)TypeScript 是什么#
TypeScript 是 JavaScript 的超集,由微软开发和维护。它在 JavaScript 基础上添加了:
- 静态类型系统:在编译时检查类型错误
- 类型推断:自动推断变量类型,减少手动标注
- 现代语法支持:支持最新的 ECMAScript 特性
- 增强的 IDE 支持:更好的代码补全、重构和导航
🤔 关键点:TypeScript 代码最终会被编译成纯 JavaScript 运行,类型信息只存在于开发阶段。
TypeScript 源码 (.ts) → 编译器 (tsc) → JavaScript 代码 (.js) → 浏览器/Node.js 执行环境搭建#
方式一:全局安装 tsc#
# 使用 npm 安装npm install -g typescript
# 验证安装tsc --version# 输出:Version 5.x.x创建并编译第一个 TypeScript 文件:
const message: string = 'Hello, TypeScript!'console.log(message)# 编译 TypeScript 文件tsc hello.ts
# 生成 hello.js 文件,然后运行node hello.js方式二:使用 ts-node(推荐开发时使用)#
ts-node 可以直接运行 TypeScript 文件,无需手动编译:
# 安装 ts-nodenpm install -g ts-node
# 直接运行 .ts 文件ts-node hello.ts方式三:使用 tsx(更快的选择)#
tsx 基于 esbuild,执行速度比 ts-node 快很多:
# 安装 tsxnpm install -g tsx
# 运行 TypeScript 文件tsx hello.ts
# 监听模式,文件变化自动重新运行tsx watch hello.ts项目初始化#
在实际项目中,通常这样初始化:
# 创建项目目录mkdir my-ts-project && cd my-ts-project
# 初始化 package.jsonnpm init -y
# 安装 TypeScript 为开发依赖npm install typescript --save-dev
# 生成 tsconfig.json 配置文件npx tsc --init生成的 tsconfig.json 包含编译器配置,关键选项:
{ "compilerOptions": { "target": "ES2020", // 编译目标版本 "module": "commonjs", // 模块系统 "strict": true, // 启用所有严格类型检查 "esModuleInterop": true, // ES 模块互操作 "outDir": "./dist", // 输出目录 "rootDir": "./src" // 源码目录 }, "include": ["src/**/*"], "exclude": ["node_modules"]}第一个 TypeScript 程序#
创建 src/index.ts:
// TypeScript 5.x
// 基础类型注解const username: string = '张三'const age: number = 25const isActive: boolean = true
// 函数类型注解function greet(name: string): string { return `你好,${name}!`}
// 对象类型(使用接口)interface User { id: number name: string email: string age?: number // 可选属性}
// 使用接口约束对象const user: User = { id: 1, name: '张三', email: 'zhangsan@example.com',}
// 数组类型const scores: number[] = [95, 88, 92]const names: Array<string> = ['张三', '李四', '王五']
// 类型推断:不需要显式标注const count = 10 // TypeScript 自动推断为 numberconst greeting = greet(username) // 自动推断返回值为 string
console.log(greeting)console.log(`${user.name} 的分数:${scores.join(', ')}`)运行:
npx tsx src/index.ts# 或编译后运行npx tsc && node dist/index.js类型推断#
TypeScript 有强大的类型推断能力,很多时候不需要手动标注类型:
// 变量初始化时自动推断let message = 'Hello' // 推断为 stringlet count = 42 // 推断为 numberlet items = [1, 2, 3] // 推断为 number[]
// 函数返回值自动推断function add(a: number, b: number) { return a + b // 返回值推断为 number}
// 上下文推断const numbers = [1, 2, 3]numbers.forEach((num) => { // num 自动推断为 number console.log(num.toFixed(2))})🔶 建议:对于函数参数,始终添加类型注解;对于有明确初始值的变量,可以依赖类型推断。
TypeScript vs JavaScript 对比#
| 特性 | JavaScript | TypeScript |
|---|---|---|
| 类型系统 | 动态类型 | 静态类型 |
| 错误发现 | 运行时 | 编译时 |
| IDE 支持 | 有限 | 完整的智能提示 |
| 学习曲线 | 低 | 中等 |
| 代码重构 | 困难 | 安全可靠 |
| 文件扩展名 | .js | .ts / .tsx |
常见问题#
🙋 TypeScript 会让代码运行变慢吗?#
不会。TypeScript 在编译阶段完成类型检查,编译后的 JavaScript 代码和手写的 JavaScript 没有区别。类型信息不会出现在运行时代码中。
🙋 现有的 JavaScript 项目能迁移到 TypeScript 吗?#
可以渐进式迁移。TypeScript 兼容所有 JavaScript 代码,你可以:
- 把
.js文件重命名为.ts - 在
tsconfig.json中设置"allowJs": true - 逐步添加类型注解
🙋 TypeScript 和 Flow 有什么区别?#
两者都是 JavaScript 的类型检查工具,但 TypeScript 是一门完整的语言,拥有更活跃的社区和更完善的工具链。目前 TypeScript 已成为事实标准。
下一步#
掌握了基础环境后,接下来我们将深入学习 TypeScript 的类型系统,从基础类型开始:
string、number、boolean等原始类型any、unknown、never等特殊类型- 数组、元组、枚举等复合类型