第1章 初识TypeScript
本章定位:从Python开发者的视角,认知TypeScript是什么、为什么需要它、以及如何搭建开发环境。通过与Python的对比,帮助你建立对TypeScript的第一印象。
1.1 TypeScript是什么
Section titled “1.1 TypeScript是什么”TypeScript由微软工程师Anders Hejlsberg(也是C#之父)于2012年设计开发。最初目的是解决JavaScript在大型项目中的可维护性问题。如今TypeScript已成为前端领域最流行的语言之一,被用于Angular框架、VS Code编辑器和许多现代Web应用。
版本演进:
- 2012年:TypeScript 0.8 发布
- 2014年:TypeScript 1.0 正式发布
- 2016年:TypeScript 2.0 发布,添加了非空类型、控制流分析等重要特性
- 2018年:TypeScript 2.7 引入了固定分配类型推断
- 2020年:TypeScript 4.0 引入了可变元组类型
- 2023年:TypeScript 5.0 引入了装饰器标准化支持
- 2024年至今:持续迭代,最新版本性能与功能双提升
TypeScript是JavaScript的超集(superset),这意味着:
- 任何有效的JavaScript代码都是有效的TypeScript代码
- TypeScript最终会被编译(transpile)成JavaScript来运行
- TypeScript添加了可选的静态类型、接口、泛型等高级特性
Python对比:Python是解释型语言,代码直接由Python解释器执行。TypeScript需要先编译(转译)为JavaScript,这类似于Python的.py文件被CPython解释器读取前的预处理过程,只是TypeScript的编译是显式的、强制性的。
TypeScript的工作原理
Section titled “TypeScript的工作原理”TypeScript源码 (.ts/.tsx) ↓ [tsc编译器转译]JavaScript代码 (.js) ↓ [Node.js或浏览器执行]程序运行结果编译器(tsc)负责:
- 类型检查
- 语法转译(将新语法转为ES5/ES6等兼容版本)
- 输出优化
静态类型检查的价值
Section titled “静态类型检查的价值”静态类型检查能在编译阶段发现大量错误,而不是等到运行时才暴露问题。
// TypeScript 编译错误示例function divide(a: number, b: number): number { return a / b;}
const result: string = divide(10, 2); // 错误:不能将number赋值给stringPython的等效代码(无编译时检查):
def divide(a: float, b: float) -> float: return a / b
result: str = divide(10, 2) # Python解释器不报错,只有运行才知道类型不匹配1.2 TypeScript vs JavaScript vs Python
Section titled “1.2 TypeScript vs JavaScript vs Python”语言类型对比
Section titled “语言类型对比”| 属性 | TypeScript | JavaScript | Python |
|---|---|---|---|
| 类型系统 | 静态类型(可选) | 动态类型 | 动态类型(可选type hint) |
| 编译/解释 | 编译为JS后运行 | 解释执行 | 解释执行 |
| 执行环境 | Node.js/浏览器/其他JS引擎 | Node.js/浏览器/其他JS引擎 | CPython/PyPy/其他Python实现 |
| 类型检查时机 | 编译时(强制) | 无(运行时) | 无强制编译时检查 |
| null/undefined | 有明确区分 | 两者混用 | 只有None |
| 面向对象 | 类、接口、抽象类、泛型 | 原型链继承 | 类、继承、多继承 |
| 函数式编程 | 支持(箭头函数、高阶函数) | 支持 | 支持(lambda、map、filter) |
| 模块系统 | ES Modules + namespace | CommonJS/ES Modules | import/from |
| 主要用途 | 前端/后端/Node.js全栈 | 前端/后端/Node.js全栈 | 后端/数据科学/脚本/AI |
类型系统深度对比
Section titled “类型系统深度对比”JavaScript(动态类型):
let x = 10; // numberx = "hello"; // 完全合法,类型可以随时改变x = [1, 2, 3]; // 数组也没问题TypeScript(静态类型,可选):
let x: number = 10; // 显式类型标注x = "hello"; // 编译错误!// 但如果不标注类型,TypeScript会进行类型推断let y = 10; // TypeScript推断为numbery = "hello"; // 编译错误!(类型推断有效)Python(动态类型 + type hint):
x = 10 # 动态类型,不做检查x = "hello" # 完全可以x: int = 10 # type hint,但仅供阅读,不强制x = "hello" # Python解释器完全允许空值处理对比
Section titled “空值处理对比”Python:只有 None
def greet(name: str | None) -> str: if name is None: return "Hello, stranger!" return f"Hello, {name}!"
print(greet(None)) # 输出: Hello, stranger!print(greet("Alice")) # 输出: Hello, Alice!TypeScript:区分 null 和 undefined
function greet(name: string | null | undefined): string { if (name === null || name === undefined) { return "Hello, stranger!"; } return `Hello, ${name}!`;}
console.log(greet(undefined)); // 输出: Hello, stranger!console.log(greet(null)); // 输出: Hello, stranger!console.log(greet("Alice")); // 输出: Hello, Alice!执行模型对比
Section titled “执行模型对比”Python执行模型:
源代码 → 字节码 → Python虚拟机 → 操作系统(.py) (.pyc)TypeScript/JavaScript执行模型:
源代码 → 解释器/编译器 → 运行时 → 操作系统(.ts) (V8/SpiderMonkey)1.3 为什么Python程序员需要TypeScript
Section titled “1.3 为什么Python程序员需要TypeScript”现代Web开发趋势
Section titled “现代Web开发趋势”如果你计划进入Web开发领域,TypeScript几乎是必备技能:
- 前端框架首选:React、Vue 3、Angular 都推荐使用TypeScript
- VS Code等工具:微软自家的VS Code本身就是用TypeScript开发的
- Node.js后端:越来越多的Node.js项目采用TypeScript以获得更好的可维护性
- 全栈统一:前后端都使用TypeScript,类型可以共享
从Python到TypeScript的知识迁移
Section titled “从Python到TypeScript的知识迁移”| Python概念 | TypeScript对应 | 备注 |
|---|---|---|
def | function / 箭头函数 | 函数声明方式不同 |
type hint | 类型注解 | TS更强制,编译时检查 |
class | class | 语法相似,TS有访问修饰符 |
None | null / undefined | TS区分两者 |
import | import | 模块语法几乎相同 |
isinstance() | typeof / instanceof | 类型检查手段不同 |
typing 模块 | 内置类型系统 | 功能类似但TS更强大 |
装饰器 @decorator | @decorator | 语法几乎相同(TS需配置) |
根据2024年Stack Overflow调查,TypeScript是第四大最受欢迎的编程语言,而JavaScript是第一。掌握TypeScript能显著提升在前端/全栈领域的竞争力。
学习曲线评估
Section titled “学习曲线评估”对Python开发者来说:
学习难度评估(1-5星,5最难):Python基础: ★☆☆☆☆Python进阶: ★★★☆☆TypeScript基础: ★★☆☆☆TypeScript类型系统: ★★★★☆TypeScript泛型: ★★★★★主要挑战在于:
- 理解静态类型的好处与约束
- 掌握泛型(类似Python的泛型但语法不同)
- 适应编译-运行两步流程
1.4 开发环境搭建
Section titled “1.4 开发环境搭建”1.4.1 安装Node.js
Section titled “1.4.1 安装Node.js”Node.js是运行TypeScript代码的基础环境。
macOS使用Homebrew:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"brew install nodeWindows使用Chocolatey:
choco install nodejs或直接从官网下载: 访问 https://nodejs.org ,下载LTS(长期支持)版本。
验证安装:
node --version # 显示Node.js版本,如 v20.10.0npm --version # 显示npm版本,如 10.2.01.4.2 安装TypeScript编译器
Section titled “1.4.2 安装TypeScript编译器”全局安装TypeScript编译器:
npm install -g typescript
# 或使用npx直接运行(无需全局安装)npx tsc --version验证安装:
tsc --version # 显示TypeScript版本,如 Version 5.3.31.4.3 创建第一个TypeScript项目
Section titled “1.4.3 创建第一个TypeScript项目”方法一:手动创建
Section titled “方法一:手动创建”mkdir my-ts-projectcd my-ts-projectnpm init -y # 初始化npm项目npm install typescript --save-dev # 安装TypeScript为开发依赖npx tsc --init # 生成tsconfig.json方法二:使用模板
Section titled “方法二:使用模板”# 使用官方tsconfig模板npx tsc --init --target es6 --module commonjs --strict truemy-ts-project/├── node_modules/ # 依赖包├── src/ # 源代码目录│ ├── index.ts│ └── utils.ts├── dist/ # 编译输出目录├── package.json # npm配置├── package-lock.json└── tsconfig.json # TypeScript配置1.4.4 tsconfig.json 详解
Section titled “1.4.4 tsconfig.json 详解”这是TypeScript编译器的配置文件,了解各选项非常重要:
{ "compilerOptions": { /* 基本选项 */ "target": "ES2020", // 编译目标JavaScript版本 "module": "commonjs", // 模块系统 "lib": ["ES2020"], // 包含的库类型定义
/* 输出控制 */ "outDir": "./dist", // 编译输出目录 "rootDir": "./src", // 源代码目录 "removeComments": true, // 移除注释 "noEmitOnError": true, // 错误时不生成文件
/* 类型检查(严格模式) */ "strict": true, // 启用所有严格类型检查 "noImplicitAny": true, // 不允许隐式any类型 "strictNullChecks": true, // 严格null检查 "strictPropertyInitialization": true, // 类属性必须初始化
/* 模块解析 */ "moduleResolution": "node", // Node.js风格解析 "esModuleInterop": true, // 允许默认导入 "resolveJsonModule": true, // 支持JSON模块
/* 实验性选项 */ "experimentalDecorators": true, // 启用装饰器 "emitDecoratorMetadata": true // 装饰器元数据 }, "include": ["src/**/*"], // 包含的文件 "exclude": ["node_modules", "dist"] // 排除的文件}1.4.5 常用IDE推荐
Section titled “1.4.5 常用IDE推荐”VS Code(推荐):
- 安装
TypeScript Nightly扩展(微软官方) - 安装
ESLint扩展 - 快捷键:
Cmd/Ctrl + Shift + P→ “TypeScript: Select TypeScript Version” → 选择工作区版本
WebStorm/JetBrains:
- 原生支持TypeScript,配置最少
1.4.6 开发工作流
Section titled “1.4.6 开发工作流”编译单个文件:
tsc src/index.ts# 生成 src/index.js监视模式(文件变化自动编译):
tsc --watch# 或tsc -w编译整个项目:
tsc# 读取tsconfig.json,编译所有文件运行编译后的JavaScript:
node dist/index.js1.5 第一个TypeScript程序 vs 第一个Python程序
Section titled “1.5 第一个TypeScript程序 vs 第一个Python程序”基础语法对比
Section titled “基础语法对比”最简单的输出
Section titled “最简单的输出”Python:
print("Hello, Python!")TypeScript:
console.log("Hello, TypeScript!");Python:
# Python 3.6+ 变量注解(可选)name: str = "Alice"age: int = 30is_student: bool = False
# 类型可以推断score = 95.5 # Python不会强制检查TypeScript:
// 显式类型标注let name: string = "Alice";let age: number = 30;let isStudent: boolean = false;
// 类型推断let score = 95.5; // TypeScript推断为number
// 编译时检查name = 123; // 错误!类型不匹配Python:
def add(a: int, b: int) -> int: return a + b
def greet(name: str, greeting: str = "Hello") -> str: return f"{greeting}, {name}!"
# 默认参数result = add(1, 2) # 3message = greet("Alice") # "Hello, Alice!"message2 = greet("Bob", "Hi") # "Hi, Bob!"TypeScript:
// 箭头函数const add = (a: number, b: number): number => { return a + b;};
// 函数声明function greet(name: string, greeting: string = "Hello"): string { return `${greeting}, ${name}!`;}
// 默认参数const result = add(1, 2); // 3const message = greet("Alice"); // "Hello, Alice!"const message2 = greet("Bob", "Hi"); // "Hi, Bob!"Python:
age = 20
if age >= 18: print("成年人")elif age >= 13: print("青少年")else: print("儿童")TypeScript:
const age: number = 20;
if (age >= 18) { console.log("成年人");} else if (age >= 13) { console.log("青少年");} else { console.log("儿童");}Python:
# for循环fruits = ["apple", "banana", "cherry"]for fruit in fruits: print(fruit)
# 带索引的循环for i, fruit in enumerate(fruits): print(f"{i}: {fruit}")
# while循环count = 0while count < 5: print(count) count += 1TypeScript:
// for循环const fruits: string[] = ["apple", "banana", "cherry"];for (const fruit of fruits) { console.log(fruit);}
// 带索引的循环fruits.forEach((fruit, i) => { console.log(`${i}: ${fruit}`);});
// while循环let count: number = 0;while (count < 5) { console.log(count); count++;}列表/数组操作
Section titled “列表/数组操作”Python:
numbers = [1, 2, 3, 4, 5]
# mapdoubled = list(map(lambda x: x * 2, numbers))
# filterevens = list(filter(lambda x: x % 2 == 0, numbers))
# reducefrom functools import reducetotal = reduce(lambda acc, x: acc + x, numbers, 0)
# 列表推导式squares = [x**2 for x in numbers]even_squares = [x**2 for x in numbers if x % 2 == 0]TypeScript:
const numbers: number[] = [1, 2, 3, 4, 5];
// mapconst doubled = numbers.map(x => x * 2);
// filterconst evens = numbers.filter(x => x % 2 === 0);
// reduceconst total = numbers.reduce((acc, x) => acc + x, 0);
// 函数式方法链const result = numbers .filter(x => x % 2 === 0) .map(x => x ** 2) .reduce((acc, x) => acc + x, 0);完整项目对比
Section titled “完整项目对比”Python项目结构
Section titled “Python项目结构”my_python_project/├── __init__.py├── main.py├── utils.py├── requirements.txt└── tests/ └── test_utils.pyutils.py:
def calculate_sum(numbers: list[int]) -> int: """计算列表所有元素的和""" return sum(numbers)
def filter_positive(numbers: list[int]) -> list[int]: """过滤出正数""" return [n for n in numbers if n > 0]main.py:
from utils import calculate_sum, filter_positive
def main(): numbers = [-1, 2, -3, 4, 5, -6] positives = filter_positive(numbers) total = calculate_sum(positives) print(f"正数和: {total}")
if __name__ == "__main__": main()运行:python main.py
TypeScript项目结构
Section titled “TypeScript项目结构”my_ts_project/├── src/│ ├── utils.ts│ └── main.ts├── package.json├── tsconfig.json└── dist/ (编译输出)src/utils.ts:
/** * 计算列表所有元素的和 */function calculateSum(numbers: number[]): number { return numbers.reduce((acc, x) => acc + x, 0);}
/** * 过滤出正数 */function filterPositive(numbers: number[]): number[] { return numbers.filter(n => n > 0);}
export { calculateSum, filterPositive };src/main.ts:
import { calculateSum, filterPositive } from "./utils";
function main(): void { const numbers: number[] = [-1, 2, -3, 4, 5, -6]; const positives: number[] = filterPositive(numbers); const total: number = calculateSum(positives); console.log(`正数和: ${total}`);}
main();编译运行:
tscnode dist/main.jsTypeScript独特的优势
Section titled “TypeScript独特的优势”编译时类型检查
Section titled “编译时类型检查”// 这段代码在编译时就会报错const user: { name: string; age: number } = { name: "Alice", age: 30};
user.age = "thirty"; // 编译错误!类型不匹配Python不会报错,只有运行时才知道有问题。
接口与类型别名
Section titled “接口与类型别名”// 定义数据结构interface User { name: string; age: number; email?: string; // 可选属性}
type Point = { x: number; y: number;};
// 编译时检查function printUser(user: User): void { console.log(`${user.name}, ${user.age}`); if (user.email) { console.log(`Email: ${user.email}`); }}
const user: User = { name: "Alice", age: 30 };printUser(user); // 正常printUser({ name: "Bob" }); // 编译错误!缺少age属性Python的等效代码(无编译时检查):
from dataclasses import dataclassfrom typing import Optional
@dataclassclass User: name: str age: int email: Optional[str] = None
def print_user(user: User) -> None: print(f"{user.name}, {user.age}") if user.email: print(f"Email: {user.email}")
# Python允许缺少属性,无法在运行前发现user = User(name="Alice") # 报错:缺少必需参数age1.6 本章小结
Section titled “1.6 本章小结”本章从Python开发者的视角认识了TypeScript:
-
TypeScript是什么:JavaScript的超集,添加了静态类型系统和面向对象特性,需要编译为JavaScript执行
-
与Python的区别:
- TypeScript编译时做类型检查,Python主要靠运行时
- TypeScript区分null和undefined,Python只有None
- TypeScript需要两步(编译+运行),Python一步(解释执行)
-
为什么学TypeScript:
- 现代Web开发必备技能
- 前后端都可使用,类型可共享
- 在大型项目中比纯JavaScript更易维护
-
开发环境:
- 需要Node.js和npm
- 全局安装TypeScript编译器
tsc - 项目需要
tsconfig.json配置文件
-
第一个程序:
- Python用
def定义函数,TypeScript用function或箭头函数 - Python用缩进,TypeScript用大括号
- 模块系统类似(import/export)
- Python用
练习1.1:环境搭建
Section titled “练习1.1:环境搭建”在本地环境完成以下任务:
- 安装Node.js(如果已安装,跳过此步)
- 安装TypeScript编译器
- 验证
tsc --version输出版本号
练习1.2:第一个程序
Section titled “练习1.2:第一个程序”创建一个TypeScript程序,实现以下功能:
- 定义一个函数,接受数字数组,返回所有偶数的和
- 在main函数中测试这个函数
- 编译并运行
练习1.3:修改严格级别
Section titled “练习1.3:修改严格级别”- 在
tsconfig.json中将strict设为false - 尝试编写一段类型不匹配的代码
- 观察编译结果
- 将
strict改回true,再次编译观察差异
练习1.4:阅读官方文档
Section titled “练习1.4:阅读官方文档”访问 TypeScript官方文档,阅读”Getting Started”部分,了解最新的TypeScript特性。
- TypeScript官网
- TypeScript GitHub仓库
- TypeScript Deep Dive(免费电子书)
- [TypeScript vs Python对比文章](https:// articles about ts vs python)
下一章我们将深入学习TypeScript的类型系统,理解静态类型如何让代码更健壮,以及Python的type hint与TypeScript类型注解的异同。