一、为什么需要 TypeScript?
JavaScript 是一门动态类型语言,灵活但容易在运行时出现类型相关的错误。TypeScript 作为 JavaScript 的超集,添加了**静态类型系统**,可以在代码运行前发现潜在错误,提升开发体验和代码可维护性。
**主要优势:**
-
静态类型检查,提前发现错误
-
更好的代码提示和自动补全
-
更清晰的自文档化代码
-
支持最新的 ECMAScript 特性
二、环境搭建与快速开始
2.1 安装 TypeScript
```bash
全局安装 TypeScript
npm install -g typescript
检查版本
tsc --version
2.2 第一个 TS 程序
创建 hello.ts 文件:
typescript
// hello.ts
function greet(name: string): string {
return `Hello, ${name}!`;
}
const message = greet("TypeScript");
console.log(message);
编译运行:
bash
# 编译为 JavaScript
tsc hello.ts
# 运行生成的 JS 文件
node hello.js
三、基础数据类型
TypeScript 支持 JavaScript 的所有类型,并增加了额外的类型注解。
3.1 原始类型
typescript
// 布尔值let isDone: boolean = false;
// 数字(整数和浮点数)
let age: number = 25;
let price: number = 99.99;
// 字符串
let name: string = "Alice";
let greeting: string = `Hello, ${name}`;
// 空值(void)
function logMessage(message: string): void {
console.log(message);
}
// null 和 undefined
let u: undefined = undefined;
let n: null = null;
3.2 数组和元组
typescript
// 数组两种声明方式
let list1: number[] = [1, 2, 3];
let list2: Array<string> = ["a", "b", "c"];
// 元组(固定长度和类型的数组)
let person: [string, number] = ["John", 30];
// 访问元组元素
console.log(person[0]); // John
console.log(person[1]); // 30
3.3 枚举(enum)
typescript
// 数字枚举
enum Direction {
Up, // 0
Down, // 1
Left, // 2
Right // 3
}
// 字符串枚举
enum Color {
Red = "RED",
Green = "GREEN",
Blue = "BLUE"
}
let dir: Direction = Direction.Up;
let color: Color = Color.Red;
3.4 Any 和 Unknown
typescript
// any - 关闭类型检查(尽量避免使用)
let notSure: any = 4;
notSure = "maybe a string";
notSure = false;
// unknown - 更安全的 any(需要类型收窄)
let uncertain: unknown = "hello";
// uncertain.toUpperCase(); // 错误:unknown 不能直接调用方法
// 类型收窄后才能使用
if (typeof uncertain === "string") {
console.log(uncertain.toUpperCase());
}
四、接口(Interface)
接口定义对象的结构契约,是 TypeScript 最核心的特性之一。
4.1 基础接口
typescript
// 定义用户接口
interface User {
id: number;
name: string;
email: string;
age?: number; // 可选属性
readonly createdAt: Date; // 只读属性
}
// 使用接口
const user: User = {
id: 1,
name: "Alice",
email: "alice@example.com",
createdAt: new Date()
};
// user.createdAt = new Date(); // 错误:只读属性不能修改
4.2 函数类型接口
typescript
interface GreetFunction {
(name: string, age: number): string;
}
const greet: GreetFunction = (name, age) => {
return `${name} is ${age} years old`;
};
4.3 接口继承
typescript
interface Animal {
name: string;
eat(): void;
}
interface Dog extends Animal {
breed: string;
bark(): void;
}
const myDog: Dog = {
name: "Buddy",
breed: "Golden Retriever",
eat() {
console.log(`${this.name} is eating`);
},
bark() {
console.log("Woof!");
}
};
五、函数高级特性
5.1 函数类型注解
typescript
// 完整函数类型
let myAdd: (x: number, y: number) => number = function(x, y) {
return x + y;
};
// 可选参数和默认参数
function buildName(firstName: string, lastName?: string, title: string = "Mr."): string {
if (lastName) {
return `${title} ${firstName} ${lastName}`;
}
return `${title} ${firstName}`;
}
console.log(buildName("John")); // Mr. John
console.log(buildName("John", "Doe")); // Mr. John Doe
console.log(buildName("John", "Doe", "Dr.")); // Dr. John Doe
5.2 剩余参数
typescript
function sum(...numbers: number[]): number {
return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3, 4)); // 10
5.3 函数重载
typescript
// 重载签名
function reverse(str: string): string;
function reverse(arr: any[]): any[];
// 实现签名
function reverse(value: string | any[]): string | any[] {
if (typeof value === "string") {
return value.split("").reverse().join("");
}
return [...value].reverse();
}
console.log(reverse("hello")); // "olleh"
console.log(reverse([1, 2, 3])); // [3, 2, 1]
六、高级类型
6.1 联合类型和交叉类型
typescript
// 联合类型(或)
type StringOrNumber = string | number;
let value: StringOrNumber = "hello";
value = 123;
// 交叉类型(且)
interface Name {
name: string;
}
interface Age {
age: number;
}
type Person = Name & Age;
const p: Person = { name: "Bob", age: 25 };
6.2 类型别名(type)
typescript
type Point = {
x: number;
y: number;
};
type ID = string | number;
function getPoint(): Point {
return { x: 10, y: 20 };
}
6.3 类型断言
typescript
// 两种语法
let someValue: any = "this is a string";
let strLength1: number = (someValue as string).length;
let strLength2: number = (<string>someValue).length;
6.4 字面量类型
typescript
type Direction = "up" | "down" | "left" | "right";
let move: Direction = "up"; // 只能赋值这四个值之一
type Status = 200 | 404 | 500;
let responseStatus: Status = 200;
七、泛型(Generics)
泛型让你创建可重用的组件,能够处理多种类型。
7.1 泛型函数
typescript
// 基础泛型
function identity<T>(arg: T): T {
return arg;
}
// 使用泛型函数
let output1 = identity<string>("hello");
let output2 = identity(100); // 类型推断
// 泛型约束
interface Lengthwise {
length: number;
}
function logLength<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}
logLength("hello"); // 5
logLength([1, 2, 3]); // 3
// logLength(123); // 错误:数字没有 length 属性
7.2 泛型接口
typescript
interface GenericIdentityFn<T> {
(arg: T): T;
}
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn<number> = identity;
7.3 泛型类
typescript
class Stack<T> {
private items: T[] = [];
push(item: T): void {
this.items.push(item);
}
pop(): T | undefined {
return this.items.pop();
}
peek(): T | undefined {
return this.items[this.items.length - 1];
}
}
const numberStack = new Stack<number>();
numberStack.push(1);
numberStack.push(2);
console.log(numberStack.pop()); // 2
const stringStack = new Stack<string>();
stringStack.push("hello");
7.4 泛型工具类型
typescript
// Partial<T> - 将所有属性变为可选
interface Todo {
title: string;
description: string;
}
function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>) {
return { ...todo, ...fieldsToUpdate };
}
// Readonly<T> - 将所有属性变为只读
const todo: Readonly<Todo> = {
title: "Learn TS",
description: "Study TypeScript"
};
// todo.title = "New title"; // 错误
// Pick<T, K> - 选取部分属性
type TodoPreview = Pick<Todo, "title">;
// Record<K, T> - 创建键值对类型
type PageInfo = Record<string, string>;
const pages: PageInfo = {
home: "/home",
about: "/about"
};
八、TypeScript 项目配置
8.1 初始化配置文件
bash
# 生成 tsconfig.json
tsc --init
8.2 核心配置选项
json
{
"compilerOptions": {
// 语言和环境
"target": "ES2020", // 编译目标版本
"lib": ["ES2020", "DOM"], // 包含的库文件
"module": "commonjs", // 模块系统
"moduleResolution": "node", // 模块解析策略
// 输出配置
"outDir": "./dist", // 输出目录
"rootDir": "./src", // 源码目录
"removeComments": true, // 移除注释
// 严格模式(推荐全部开启)
"strict": true, // 启用所有严格检查
"noImplicitAny": true, // 禁止隐式 any
"strictNullChecks": true, // 严格空值检查
"strictFunctionTypes": true, // 严格函数类型检查
// 额外检查
"noUnusedLocals": true, // 未使用的局部变量报错
"noUnusedParameters": true, // 未使用的参数报错
"noImplicitReturns": true, // 函数缺少返回值报错
// 模块解析
"esModuleInterop": true, // 兼容 CommonJS 和 ES 模块
"skipLibCheck": true, // 跳过声明文件检查
"forceConsistentCasingInFileNames": true // 强制文件名大小写一致
},
"include": ["src/**/*"], // 包含的文件
"exclude": ["node_modules", "dist"] // 排除的文件
}
8.3 项目结构示例
text
my-ts-project/
├── src/
│ ├── models/
│ │ └── user.ts
│ ├── services/
│ │ └── api.ts
│ └── index.ts
├── dist/ # 编译输出
├── tsconfig.json
├── package.json
└── .gitignore
8.4 使用 npm 脚本
json
{
"scripts": {
"build": "tsc",
"watch": "tsc --watch",
"start": "node dist/index.js",
"dev": "tsc --watch & nodemon dist/index.js"
},
"devDependencies": {
"typescript": "^5.0.0",
"@types/node": "^20.0.0"
}
}
九、实际应用示例
9.1 结合 Express 使用
typescript
import express, { Request, Response } from 'express';
interface User {
id: number;
name: string;
email: string;
}
const app = express();
app.use(express.json());
const users: User[] = [];
app.get('/users', (req: Request, res: Response) => {
res.json(users);
});
app.post('/users', (req: Request, res: Response) => {
const { name, email } = req.body;
const newUser: User = {
id: users.length + 1,
name,
email
};
users.push(newUser);
res.status(201).json(newUser);
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
9.2 类型声明文件(.d.ts)
typescript
// types.d.ts - 为第三方库或全局变量提供类型
declare module 'my-library' {
export function doSomething(param: string): number;
}
// 声明全局变量
declare const __VERSION__: string;
declare const __API_URL__: string;
十、最佳实践总结
-
开启严格模式 :
"strict": true捕获更多潜在错误 -
避免使用 any :使用
unknown或具体类型代替 -
善用类型推断:让 TypeScript 自动推断简单类型
-
接口优先 :定义对象结构时优先使用
interface -
泛型复用:为可复用逻辑编写泛型组件
-
明确函数返回类型:显式标注返回值提高可读性
-
使用可选链和空值合并 :
?.和??简化空值处理 -
定期更新 TypeScript:获取最新特性和性能改进
结语
TypeScript 已经成为现代前端和后端(Node.js)开发的标准工具。掌握 TypeScript 不仅能提高代码质量,还能让你在团队协作中更加高效。建议你在实际项目中逐步应用这些知识,从简单的类型注解开始,逐渐过渡到高级类型和泛型的使用。
推荐学习资源:
本文完,希望对你学习 TypeScript 有所帮助!欢迎在评论区交流讨论。