Skip to content

初识 TypeScript

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.x
function 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 基础上添加了:

🤔 关键点:TypeScript 代码最终会被编译成纯 JavaScript 运行,类型信息只存在于开发阶段。

TypeScript 源码 (.ts) → 编译器 (tsc) → JavaScript 代码 (.js) → 浏览器/Node.js 执行

环境搭建#

方式一:全局安装 tsc#

Terminal window
# 使用 npm 安装
npm install -g typescript
# 验证安装
tsc --version
# 输出:Version 5.x.x

创建并编译第一个 TypeScript 文件:

hello.ts
const message: string = 'Hello, TypeScript!'
console.log(message)
Terminal window
# 编译 TypeScript 文件
tsc hello.ts
# 生成 hello.js 文件,然后运行
node hello.js

方式二:使用 ts-node(推荐开发时使用)#

ts-node 可以直接运行 TypeScript 文件,无需手动编译:

Terminal window
# 安装 ts-node
npm install -g ts-node
# 直接运行 .ts 文件
ts-node hello.ts

方式三:使用 tsx(更快的选择)#

tsx 基于 esbuild,执行速度比 ts-node 快很多:

Terminal window
# 安装 tsx
npm install -g tsx
# 运行 TypeScript 文件
tsx hello.ts
# 监听模式,文件变化自动重新运行
tsx watch hello.ts

项目初始化#

在实际项目中,通常这样初始化:

Terminal window
# 创建项目目录
mkdir my-ts-project && cd my-ts-project
# 初始化 package.json
npm 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 = 25
const 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 自动推断为 number
const greeting = greet(username) // 自动推断返回值为 string
console.log(greeting)
console.log(`${user.name} 的分数:${scores.join(', ')}`)

运行:

Terminal window
npx tsx src/index.ts
# 或编译后运行
npx tsc && node dist/index.js

类型推断#

TypeScript 有强大的类型推断能力,很多时候不需要手动标注类型:

// 变量初始化时自动推断
let message = 'Hello' // 推断为 string
let count = 42 // 推断为 number
let 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 对比#

特性JavaScriptTypeScript
类型系统动态类型静态类型
错误发现运行时编译时
IDE 支持有限完整的智能提示
学习曲线中等
代码重构困难安全可靠
文件扩展名.js.ts / .tsx

常见问题#

🙋 TypeScript 会让代码运行变慢吗?#

不会。TypeScript 在编译阶段完成类型检查,编译后的 JavaScript 代码和手写的 JavaScript 没有区别。类型信息不会出现在运行时代码中。

🙋 现有的 JavaScript 项目能迁移到 TypeScript 吗?#

可以渐进式迁移。TypeScript 兼容所有 JavaScript 代码,你可以:

  1. .js 文件重命名为 .ts
  2. tsconfig.json 中设置 "allowJs": true
  3. 逐步添加类型注解

🙋 TypeScript 和 Flow 有什么区别?#

两者都是 JavaScript 的类型检查工具,但 TypeScript 是一门完整的语言,拥有更活跃的社区和更完善的工具链。目前 TypeScript 已成为事实标准。

下一步#

掌握了基础环境后,接下来我们将深入学习 TypeScript 的类型系统,从基础类型开始: