Appearance
TypeScript 实战综合案例
本章节将通过几个综合案例,展示 TypeScript 在实际项目中的应用,帮助你理解如何在真实场景中使用 TypeScript。
接口定义接口数据结构
示例:定义 API 接口数据结构
typescript
// 定义用户接口
interface User {
id: number;
name: string;
email: string;
age?: number;
address?: {
street: string;
city: string;
country: string;
};
createdAt: string;
updatedAt: string;
}
// 定义产品接口
interface Product {
id: number;
name: string;
price: number;
description: string;
category: string;
stock: number;
imageUrl: string;
createdAt: string;
updatedAt: string;
}
// 定义订单接口
interface Order {
id: number;
userId: number;
user?: User;
items: OrderItem[];
total: number;
status: "pending" | "processing" | "shipped" | "delivered" | "cancelled";
createdAt: string;
updatedAt: string;
}
// 定义订单项接口
interface OrderItem {
id: number;
orderId: number;
productId: number;
product?: Product;
quantity: number;
price: number;
}
// 定义 API 响应接口
interface ApiResponse<T> {
success: boolean;
data?: T;
error?: {
code: number;
message: string;
};
pagination?: {
page: number;
pageSize: number;
total: number;
};
}
// 使用示例
async function fetchUsers(): Promise<ApiResponse<User[]>> {
const response = await fetch('/api/users');
return response.json();
}
async function fetchProducts(): Promise<ApiResponse<Product[]>> {
const response = await fetch('/api/products');
return response.json();
}
async function fetchOrders(): Promise<ApiResponse<Order[]>> {
const response = await fetch('/api/orders');
return response.json();
}函数封装 + 泛型工具
示例:封装通用 API 客户端
typescript
// 定义 API 客户端
class ApiClient {
private baseUrl: string;
constructor(baseUrl: string) {
this.baseUrl = baseUrl;
}
// 通用 GET 请求
async get<T>(endpoint: string, params?: Record<string, any>): Promise<ApiResponse<T>> {
const url = new URL(`${this.baseUrl}${endpoint}`);
if (params) {
Object.entries(params).forEach(([key, value]) => {
url.searchParams.append(key, value.toString());
});
}
const response = await fetch(url.toString());
return response.json();
}
// 通用 POST 请求
async post<T>(endpoint: string, data: any): Promise<ApiResponse<T>> {
const response = await fetch(`${this.baseUrl}${endpoint}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
return response.json();
}
// 通用 PUT 请求
async put<T>(endpoint: string, data: any): Promise<ApiResponse<T>> {
const response = await fetch(`${this.baseUrl}${endpoint}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
return response.json();
}
// 通用 DELETE 请求
async delete<T>(endpoint: string): Promise<ApiResponse<T>> {
const response = await fetch(`${this.baseUrl}${endpoint}`, {
method: 'DELETE',
});
return response.json();
}
}
// 使用示例
const apiClient = new ApiClient('https://api.example.com');
// 获取用户列表
async function getUsers() {
const response = await apiClient.get<User[]>('/users', {
page: 1,
pageSize: 10,
});
if (response.success && response.data) {
console.log(response.data);
}
}
// 创建用户
async function createUser(user: Omit<User, 'id' | 'createdAt' | 'updatedAt'>) {
const response = await apiClient.post<User>('/users', user);
if (response.success && response.data) {
console.log('User created:', response.data);
}
}
// 更新用户
async function updateUser(id: number, user: Partial<User>) {
const response = await apiClient.put<User>(`/users/${id}`, user);
if (response.success && response.data) {
console.log('User updated:', response.data);
}
}
// 删除用户
async function deleteUser(id: number) {
const response = await apiClient.delete<{ message: string }>(`/users/${id}`);
if (response.success) {
console.log(response.data?.message);
}
}类封装业务逻辑
示例:用户管理服务
typescript
// 用户服务
class UserService {
private apiClient: ApiClient;
constructor(apiClient: ApiClient) {
this.apiClient = apiClient;
}
// 获取用户列表
async getUsers(page: number = 1, pageSize: number = 10): Promise<User[]> {
const response = await this.apiClient.get<User[]>('/users', {
page,
pageSize,
});
if (!response.success || !response.data) {
throw new Error(response.error?.message || 'Failed to get users');
}
return response.data;
}
// 获取单个用户
async getUser(id: number): Promise<User> {
const response = await this.apiClient.get<User>(`/users/${id}`);
if (!response.success || !response.data) {
throw new Error(response.error?.message || 'Failed to get user');
}
return response.data;
}
// 创建用户
async createUser(userData: Omit<User, 'id' | 'createdAt' | 'updatedAt'>): Promise<User> {
const response = await this.apiClient.post<User>('/users', userData);
if (!response.success || !response.data) {
throw new Error(response.error?.message || 'Failed to create user');
}
return response.data;
}
// 更新用户
async updateUser(id: number, userData: Partial<User>): Promise<User> {
const response = await this.apiClient.put<User>(`/users/${id}`, userData);
if (!response.success || !response.data) {
throw new Error(response.error?.message || 'Failed to update user');
}
return response.data;
}
// 删除用户
async deleteUser(id: number): Promise<void> {
const response = await this.apiClient.delete<{ message: string }>(`/users/${id}`);
if (!response.success) {
throw new Error(response.error?.message || 'Failed to delete user');
}
}
// 搜索用户
async searchUsers(query: string): Promise<User[]> {
const response = await this.apiClient.get<User[]>('/users/search', {
q: query,
});
if (!response.success || !response.data) {
throw new Error(response.error?.message || 'Failed to search users');
}
return response.data;
}
}
// 使用示例
const apiClient = new ApiClient('https://api.example.com');
const userService = new UserService(apiClient);
// 获取用户列表
userService.getUsers(1, 20)
.then(users => console.log(users))
.catch(error => console.error(error));
// 创建用户
userService.createUser({
name: 'John Doe',
email: 'john@example.com',
age: 30,
address: {
street: '123 Main St',
city: 'New York',
country: 'USA',
},
})
.then(user => console.log('Created user:', user))
.catch(error => console.error(error));类型约束表单数据
示例:表单验证
typescript
// 定义表单类型
interface LoginForm {
email: string;
password: string;
rememberMe?: boolean;
}
interface RegisterForm {
name: string;
email: string;
password: string;
confirmPassword: string;
agreeToTerms: boolean;
}
// 表单验证服务
class FormValidator {
// 验证登录表单
static validateLoginForm(form: LoginForm): Partial<Record<keyof LoginForm, string>> {
const errors: Partial<Record<keyof LoginForm, string>> = {};
if (!form.email) {
errors.email = 'Email is required';
} else if (!this.isValidEmail(form.email)) {
errors.email = 'Invalid email address';
}
if (!form.password) {
errors.password = 'Password is required';
} else if (form.password.length < 8) {
errors.password = 'Password must be at least 8 characters';
}
return errors;
}
// 验证注册表单
static validateRegisterForm(form: RegisterForm): Partial<Record<keyof RegisterForm, string>> {
const errors: Partial<Record<keyof RegisterForm, string>> = {};
if (!form.name) {
errors.name = 'Name is required';
}
if (!form.email) {
errors.email = 'Email is required';
} else if (!this.isValidEmail(form.email)) {
errors.email = 'Invalid email address';
}
if (!form.password) {
errors.password = 'Password is required';
} else if (form.password.length < 8) {
errors.password = 'Password must be at least 8 characters';
}
if (!form.confirmPassword) {
errors.confirmPassword = 'Please confirm your password';
} else if (form.confirmPassword !== form.password) {
errors.confirmPassword = 'Passwords do not match';
}
if (!form.agreeToTerms) {
errors.agreeToTerms = 'You must agree to the terms and conditions';
}
return errors;
}
// 验证邮箱格式
private static isValidEmail(email: string): boolean {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
}
// 使用示例
const loginForm: LoginForm = {
email: 'john@example.com',
password: 'password123',
rememberMe: true,
};
const loginErrors = FormValidator.validateLoginForm(loginForm);
if (Object.keys(loginErrors).length === 0) {
console.log('Login form is valid');
} else {
console.log('Login form errors:', loginErrors);
}
const registerForm: RegisterForm = {
name: 'John Doe',
email: 'john@example.com',
password: 'password123',
confirmPassword: 'password123',
agreeToTerms: true,
};
const registerErrors = FormValidator.validateRegisterForm(registerForm);
if (Object.keys(registerErrors).length === 0) {
console.log('Register form is valid');
} else {
console.log('Register form errors:', registerErrors);
}TS 写一个 TodoList
示例:TodoList 应用
typescript
// 定义 Todo 类型
export interface Todo {
id: number;
title: string;
description?: string;
completed: boolean;
createdAt: string;
updatedAt: string;
}
// 定义 Todo 服务
class TodoService {
private todos: Todo[] = [];
private nextId = 1;
// 获取所有 Todo
getTodos(): Todo[] {
return this.todos;
}
// 获取单个 Todo
getTodo(id: number): Todo | undefined {
return this.todos.find(todo => todo.id === id);
}
// 创建 Todo
createTodo(todo: Omit<Todo, 'id' | 'completed' | 'createdAt' | 'updatedAt'>): Todo {
const newTodo: Todo = {
...todo,
id: this.nextId++,
completed: false,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
};
this.todos.push(newTodo);
return newTodo;
}
// 更新 Todo
updateTodo(id: number, updates: Partial<Omit<Todo, 'id' | 'createdAt' | 'updatedAt'>>): Todo | undefined {
const index = this.todos.findIndex(todo => todo.id === id);
if (index === -1) {
return undefined;
}
const updatedTodo: Todo = {
...this.todos[index],
...updates,
updatedAt: new Date().toISOString(),
};
this.todos[index] = updatedTodo;
return updatedTodo;
}
// 删除 Todo
deleteTodo(id: number): boolean {
const index = this.todos.findIndex(todo => todo.id === id);
if (index === -1) {
return false;
}
this.todos.splice(index, 1);
return true;
}
// 切换 Todo 完成状态
toggleTodo(id: number): Todo | undefined {
return this.updateTodo(id, {
completed: !this.todos.find(todo => todo.id === id)?.completed,
});
}
// 过滤 Todo
filterTodos(filter: 'all' | 'completed' | 'active'): Todo[] {
switch (filter) {
case 'completed':
return this.todos.filter(todo => todo.completed);
case 'active':
return this.todos.filter(todo => !todo.completed);
case 'all':
default:
return this.todos;
}
}
}
// 使用示例
const todoService = new TodoService();
// 创建 Todo
todoService.createTodo({
title: 'Learn TypeScript',
description: 'Study TypeScript basics and advanced features',
});
todoService.createTodo({
title: 'Build a Todo app',
description: 'Create a Todo application using TypeScript',
});
todoService.createTodo({
title: 'Practice coding',
description: 'Solve TypeScript exercises',
});
// 获取所有 Todo
console.log('All todos:', todoService.getTodos());
// 标记第一个 Todo 为完成
todoService.toggleTodo(1);
// 获取已完成的 Todo
console.log('Completed todos:', todoService.filterTodos('completed'));
// 获取未完成的 Todo
console.log('Active todos:', todoService.filterTodos('active'));
// 更新 Todo
todoService.updateTodo(2, {
title: 'Build a TypeScript Todo app',
description: 'Create a Todo application using TypeScript and React',
});
// 删除 Todo
todoService.deleteTodo(3);
// 获取所有 Todo
console.log('All todos after updates:', todoService.getTodos());实战:完整的 TypeScript 应用
示例:电商购物车应用
typescript
// 定义产品类型
export interface Product {
id: number;
name: string;
price: number;
description: string;
category: string;
stock: number;
imageUrl: string;
}
// 定义购物车项类型
export interface CartItem {
product: Product;
quantity: number;
}
// 定义购物车服务
class CartService {
private items: CartItem[] = [];
// 获取购物车项目
getItems(): CartItem[] {
return this.items;
}
// 获取购物车总数量
getTotalQuantity(): number {
return this.items.reduce((total, item) => total + item.quantity, 0);
}
// 获取购物车总金额
getTotalPrice(): number {
return this.items.reduce((total, item) => total + (item.product.price * item.quantity), 0);
}
// 添加商品到购物车
addItem(product: Product, quantity: number = 1): void {
const existingItem = this.items.find(item => item.product.id === product.id);
if (existingItem) {
// 如果商品已存在,增加数量
existingItem.quantity += quantity;
} else {
// 如果商品不存在,添加新项
this.items.push({ product, quantity });
}
}
// 从购物车移除商品
removeItem(productId: number): void {
this.items = this.items.filter(item => item.product.id !== productId);
}
// 更新购物车项数量
updateQuantity(productId: number, quantity: number): void {
const item = this.items.find(item => item.product.id === productId);
if (item) {
if (quantity <= 0) {
// 如果数量为 0 或负数,移除商品
this.removeItem(productId);
} else {
// 更新数量
item.quantity = quantity;
}
}
}
// 清空购物车
clearCart(): void {
this.items = [];
}
}
// 定义产品服务
class ProductService {
private products: Product[] = [
{
id: 1,
name: 'iPhone 13',
price: 799,
description: 'Apple iPhone 13 with A15 Bionic chip',
category: 'Electronics',
stock: 100,
imageUrl: 'https://example.com/iphone13.jpg',
},
{
id: 2,
name: 'MacBook Pro',
price: 1299,
description: 'Apple MacBook Pro with M1 chip',
category: 'Electronics',
stock: 50,
imageUrl: 'https://example.com/macbookpro.jpg',
},
{
id: 3,
name: 'AirPods Pro',
price: 199,
description: 'Apple AirPods Pro with active noise cancellation',
category: 'Electronics',
stock: 200,
imageUrl: 'https://example.com/airpodspro.jpg',
},
];
// 获取所有产品
getProducts(): Product[] {
return this.products;
}
// 根据 ID 获取产品
getProductById(id: number): Product | undefined {
return this.products.find(product => product.id === id);
}
// 根据分类获取产品
getProductsByCategory(category: string): Product[] {
return this.products.filter(product => product.category === category);
}
// 搜索产品
searchProducts(query: string): Product[] {
const lowerQuery = query.toLowerCase();
return this.products.filter(product =>
product.name.toLowerCase().includes(lowerQuery) ||
product.description.toLowerCase().includes(lowerQuery)
);
}
}
// 使用示例
const productService = new ProductService();
const cartService = new CartService();
// 获取所有产品
console.log('All products:', productService.getProducts());
// 添加商品到购物车
const product1 = productService.getProductById(1);
const product2 = productService.getProductById(2);
if (product1 && product2) {
cartService.addItem(product1, 2);
cartService.addItem(product2, 1);
}
// 获取购物车
console.log('Cart items:', cartService.getItems());
console.log('Total quantity:', cartService.getTotalQuantity());
console.log('Total price:', cartService.getTotalPrice());
// 更新购物车项数量
cartService.updateQuantity(1, 3);
console.log('Cart items after update:', cartService.getItems());
console.log('Total quantity after update:', cartService.getTotalQuantity());
console.log('Total price after update:', cartService.getTotalPrice());
// 移除商品
cartService.removeItem(2);
console.log('Cart items after removal:', cartService.getItems());
console.log('Total quantity after removal:', cartService.getTotalQuantity());
console.log('Total price after removal:', cartService.getTotalPrice());
// 清空购物车
cartService.clearCart();
console.log('Cart items after clear:', cartService.getItems());
console.log('Total quantity after clear:', cartService.getTotalQuantity());
console.log('Total price after clear:', cartService.getTotalPrice());小结
本章节通过几个综合案例,展示了 TypeScript 在实际项目中的应用:
- 接口定义接口数据结构:定义了用户、产品、订单等接口数据结构
- 函数封装 + 泛型工具:封装了通用 API 客户端,使用泛型提高代码复用性
- 类封装业务逻辑:创建了用户管理服务,封装了用户相关的业务逻辑
- 类型约束表单数据:实现了表单验证服务,确保表单数据的类型安全
- TS 写一个 TodoList:创建了 TodoList 应用,展示了 TypeScript 在状态管理中的应用
- 实战:完整的 TypeScript 应用:实现了电商购物车应用,展示了 TypeScript 在复杂应用中的应用
通过这些案例,你可以看到 TypeScript 如何帮助你构建类型安全、可维护的应用。在实际开发中,应该充分利用 TypeScript 的类型系统,提高代码的可靠性和可维护性。
