在前两篇文章中,我们学习了TypeScript的基础语法、类型系统以及复合类型和高级语法特性。今天,我们将深入学习TypeScript的面向对象编程(OOP)特性。面向对象编程是一种编程范式,它使用"对象"来设计应用程序和计算机程序。TypeScript作为JavaScript的超集,不仅支持JavaScript的函数式编程方式,还提供了完整的面向对象编程支持,包括类、继承、多态、抽象类、接口等特性。
掌握面向对象编程是成为一名优秀的TypeScript开发者的重要一步。通过面向对象编程,我们可以更好地组织和管理代码,提高代码的可复用性、可维护性和可扩展性。本文将采用循序渐进的方式,从类的基本概念开始,逐步介绍TypeScript的面向对象编程特性。通过丰富的代码示例和实战练习,帮助你快速理解和掌握这些概念。同时,我们还将结合AI技术,展示如何利用AI工具提升你的学习效率,让你能够更快地将所学知识应用到实际项目中。
要点 | 描述 |
|---|---|
痛点 | 面向对象编程概念抽象?不知道如何在TypeScript中应用? |
方案 | 详细讲解,实例演示,AI辅助解析,实战应用 |
驱动 | 掌握TypeScript面向对象编程,编写更专业、更易维护的代码! |
章节 | 内容 |
|---|---|
1 | 类的基本概念 |
2 | 继承与多态 |
3 | 抽象类与接口 |
4 | 访问修饰符 |
5 | 静态成员与单例模式 |
6 | 泛型类与泛型接口 |
7 | AI辅助学习TypeScript面向对象编程 |
8 | 实战练习:构建简单的电商系统 |
类是面向对象编程的基本单位,它是一种用于创建对象的蓝图或模板。在TypeScript中,我们可以使用class关键字来定义类。类可以包含属性(数据)和方法(行为)。
基本语法:
class 类名 {
// 属性声明
属性名: 类型;
属性名: 类型 = 默认值; // 带默认值的属性
// 构造函数
constructor(参数: 类型) {
this.属性名 = 参数;
}
// 方法
方法名(参数: 类型): 返回类型 {
// 方法体
}
}
// 创建类的实例
const 实例名 = new 类名(参数);
// 访问实例的属性和方法
实例名.属性名;
实例名.方法名(参数);示例:
// 定义一个简单的Person类
class Person {
// 属性声明
name: string;
age: number;
// 构造函数
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
// 方法
greet(): string {
return `Hello, my name is ${this.name} and I am ${this.age} years old.`;
}
// 更新年龄的方法
updateAge(newAge: number): void {
this.age = newAge;
}
}
// 创建Person类的实例
const person1 = new Person("John Doe", 30);
const person2 = new Person("Jane Smith", 25);
// 访问实例的属性和方法
console.log(person1.name); // 输出: John Doe
console.log(person1.age); // 输出: 30
console.log(person1.greet()); // 输出: Hello, my name is John Doe and I am 30 years old.
// 调用实例的方法修改属性
person1.updateAge(31);
console.log(person1.age); // 输出: 31
console.log(person2.greet()); // 输出: Hello, my name is Jane Smith and I am 25 years old.在TypeScript中,我们可以在声明属性时直接初始化它们,也可以在构造函数中初始化它们。
示例:
// 声明属性时直接初始化
class Car {
make: string = "Unknown";
model: string = "Unknown";
year: number = 2020;
constructor(make?: string, model?: string, year?: number) {
if (make) this.make = make;
if (model) this.model = model;
if (year) this.year = year;
}
displayInfo(): void {
console.log(`${this.year} ${this.make} ${this.model}`);
}
}
// 创建Car类的实例
const defaultCar = new Car();
defaultCar.displayInfo(); // 输出: 2020 Unknown Unknown
const customCar = new Car("Toyota", "Camry", 2022);
customCar.displayInfo(); // 输出: 2022 Toyota Camry
// 使用构造函数参数属性(更简洁的方式)
class Vehicle {
// 构造函数参数属性:在参数前添加访问修饰符
constructor(
public make: string = "Unknown",
public model: string = "Unknown",
public year: number = 2020
) {
// 不需要在这里重复初始化属性
}
displayInfo(): void {
console.log(`${this.year} ${this.make} ${this.model}`);
}
}
const vehicle1 = new Vehicle();
vehicle1.displayInfo(); // 输出: 2020 Unknown Unknown
const vehicle2 = new Vehicle("Honda", "Civic", 2021);
vehicle2.displayInfo(); // 输出: 2021 Honda Civic类的方法是定义在类中的函数,它可以访问类的属性和其他方法。方法可以接受参数,也可以返回值。
示例:
class Calculator {
// 基本计算方法
add(a: number, b: number): number {
return a + b;
}
subtract(a: number, b: number): number {
return a - b;
}
multiply(a: number, b: number): number {
return a * b;
}
divide(a: number, b: number): number {
if (b === 0) {
throw new Error("Division by zero is not allowed");
}
return a / b;
}
// 复合计算方法
calculateCircleArea(radius: number): number {
return Math.PI * this.multiply(radius, radius);
}
calculateRectangleArea(width: number, height: number): number {
return this.multiply(width, height);
}
}
const calculator = new Calculator();
// 调用基本计算方法
console.log(calculator.add(5, 3)); // 输出: 8
console.log(calculator.subtract(10, 4)); // 输出: 6
console.log(calculator.multiply(6, 7)); // 输出: 42
console.log(calculator.divide(20, 5)); // 输出: 4
// 调用复合计算方法
console.log(calculator.calculateCircleArea(5)); // 输出: 78.53981633974483
console.log(calculator.calculateRectangleArea(4, 6)); // 输出: 24
// 错误处理
try {
calculator.divide(10, 0);
} catch (error) {
console.error(error.message); // 输出: Division by zero is not allowed
}存取器是一种特殊的方法,用于控制对类属性的访问和修改。在TypeScript中,我们可以使用get和set关键字来定义存取器。
基本语法:
class 类名 {
private _属性名: 类型;
constructor(参数: 类型) {
this._属性名 = 参数;
}
// Getter方法
get 属性名(): 类型 {
return this._属性名;
}
// Setter方法
set 属性名(值: 类型) {
// 可以在这里添加验证逻辑
this._属性名 = 值;
}
}示例:
class Student {
private _name: string;
private _age: number;
private _grade: number;
constructor(name: string, age: number, grade: number) {
this._name = name;
this._age = age;
this._grade = grade;
}
// Getter方法
get name(): string {
return this._name;
}
// Setter方法
set name(newName: string) {
if (newName.trim() === "") {
throw new Error("Name cannot be empty");
}
this._name = newName;
}
// Getter方法
get age(): number {
return this._age;
}
// Setter方法
set age(newAge: number) {
if (newAge < 0 || newAge > 120) {
throw new Error("Age must be between 0 and 120");
}
this._age = newAge;
}
// Getter方法
get grade(): number {
return this._grade;
}
// Setter方法
set grade(newGrade: number) {
if (newGrade < 0 || newGrade > 100) {
throw new Error("Grade must be between 0 and 100");
}
this._grade = newGrade;
}
// 计算成绩等级的方法
get gradeLevel(): string {
if (this._grade >= 90) return "A";
if (this._grade >= 80) return "B";
if (this._grade >= 70) return "C";
if (this._grade >= 60) return "D";
return "F";
}
displayInfo(): void {
console.log(`${this._name}, ${this._age} years old, Grade: ${this._grade} (${this.gradeLevel})`);
}
}
const student = new Student("Alice", 16, 85);
// 使用getter访问属性
console.log(student.name); // 输出: Alice
console.log(student.age); // 输出: 16
console.log(student.grade); // 输出: 85
console.log(student.gradeLevel); // 输出: B
// 使用setter修改属性
student.name = "Alice Smith";
student.age = 17;
student.grade = 92;
student.displayInfo(); // 输出: Alice Smith, 17 years old, Grade: 92 (A)
// 错误处理
try {
student.grade = 101; // 超出范围
} catch (error) {
console.error(error.message); // 输出: Grade must be between 0 and 100
}
try {
student.name = "";
} catch (error) {
console.error(error.message); // 输出: Name cannot be empty
}继承是面向对象编程的一个重要特性,它允许我们创建一个新类(子类)来继承现有类(父类)的属性和方法。多态是另一个重要特性,它允许子类重写父类的方法,并以不同的方式实现。
在TypeScript中,我们可以使用extends关键字来实现继承。子类可以继承父类的所有属性和方法,并且可以添加自己的属性和方法,或者重写父类的方法。
基本语法:
class 父类名 {
// 父类的属性和方法
}
class 子类名 extends 父类名 {
// 子类特有的属性和方法
// 或者重写父类的方法
}示例:
// 定义一个基类(父类)
class Animal {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
eat(): void {
console.log(`${this.name} is eating.`);
}
sleep(): void {
console.log(`${this.name} is sleeping.`);
}
makeSound(): void {
console.log(`${this.name} makes a sound.`);
}
}
// 定义一个继承自Animal的子类
class Dog extends Animal {
breed: string;
constructor(name: string, age: number, breed: string) {
// 使用super关键字调用父类的构造函数
super(name, age);
this.breed = breed;
}
// 重写父类的方法
makeSound(): void {
console.log(`${this.name} barks: Woof! Woof!`);
}
// 子类特有的方法
fetch(): void {
console.log(`${this.name} is fetching the ball.`);
}
}
// 定义另一个继承自Animal的子类
class Cat extends Animal {
color: string;
constructor(name: string, age: number, color: string) {
super(name, age);
this.color = color;
}
// 重写父类的方法
makeSound(): void {
console.log(`${this.name} meows: Meow! Meow!`);
}
// 子类特有的方法
climb(): void {
console.log(`${this.name} is climbing a tree.`);
}
}
// 创建子类的实例
const dog = new Dog("Rover", 3, "Golden Retriever");
const cat = new Cat("Whiskers", 2, "Gray");
// 调用继承的方法
console.log(dog.name); // 输出: Rover
console.log(cat.age); // 输出: 2
dog.eat(); // 输出: Rover is eating.
cat.sleep(); // 输出: Whiskers is sleeping.
// 调用重写的方法(多态)
dog.makeSound(); // 输出: Rover barks: Woof! Woof!
cat.makeSound(); // 输出: Whiskers meows: Meow! Meow!
// 调用子类特有的方法
dog.fetch(); // 输出: Rover is fetching the ball.
cat.climb(); // 输出: Whiskers is climbing a tree.多态是面向对象编程的一个重要特性,它允许我们使用父类类型的变量来引用子类类型的对象,并在运行时根据对象的实际类型来调用相应的方法。
示例:
// 定义一个基类
class Shape {
name: string;
constructor(name: string) {
this.name = name;
}
// 虚方法(在子类中重写)
calculateArea(): number {
return 0; // 默认实现
}
displayInfo(): void {
console.log(`Shape: ${this.name}, Area: ${this.calculateArea()}`);
}
}
// 定义继承自Shape的子类
class Circle extends Shape {
radius: number;
constructor(name: string, radius: number) {
super(name);
this.radius = radius;
}
// 重写父类的方法
calculateArea(): number {
return Math.PI * this.radius * this.radius;
}
}
class Rectangle extends Shape {
width: number;
height: number;
constructor(name: string, width: number, height: number) {
super(name);
this.width = width;
this.height = height;
}
// 重写父类的方法
calculateArea(): number {
return this.width * this.height;
}
}
class Triangle extends Shape {
base: number;
height: number;
constructor(name: string, base: number, height: number) {
super(name);
this.base = base;
this.height = height;
}
// 重写父类的方法
calculateArea(): number {
return 0.5 * this.base * this.height;
}
}
// 创建子类的实例
const shapes: Shape[] = [
new Circle("Circle 1", 5),
new Rectangle("Rectangle 1", 4, 6),
new Triangle("Triangle 1", 3, 8)
];
// 演示多态:使用父类类型的数组存储子类类型的对象
shapes.forEach(shape => {
shape.displayInfo(); // 调用的是子类重写的方法
});
/* 输出:
Shape: Circle 1, Area: 78.53981633974483
Shape: Rectangle 1, Area: 24
Shape: Triangle 1, Area: 12
*/
// 演示多态:使用父类类型的变量引用子类类型的对象
function printArea(shape: Shape): void {
console.log(`The area of ${shape.name} is ${shape.calculateArea()}`);
}
printArea(new Circle("Small Circle", 2)); // 输出: The area of Small Circle is 12.566370614359172
printArea(new Rectangle("Big Rectangle", 10, 20)); // 输出: The area of Big Rectangle is 200在子类中,我们可以使用super关键字来调用父类的方法。这在我们想要在子类中扩展父类方法的功能时非常有用。
示例:
// 定义一个基类
class Employee {
name: string;
position: string;
salary: number;
constructor(name: string, position: string, salary: number) {
this.name = name;
this.position = position;
this.salary = salary;
}
getAnnualSalary(): number {
return this.salary * 12;
}
displayInfo(): void {
console.log(`Name: ${this.name}, Position: ${this.position}, Monthly Salary: $${this.salary}`);
}
}
// 定义继承自Employee的子类
class Manager extends Employee {
department: string;
bonus: number;
constructor(name: string, position: string, salary: number, department: string, bonus: number) {
super(name, position, salary);
this.department = department;
this.bonus = bonus;
}
// 重写父类的方法,扩展其功能
getAnnualSalary(): number {
// 使用super调用父类的方法,然后添加奖金
return super.getAnnualSalary() + this.bonus;
}
// 重写父类的方法,扩展其功能
displayInfo(): void {
// 调用父类的displayInfo方法
super.displayInfo();
// 添加额外的信息
console.log(`Department: ${this.department}, Annual Bonus: $${this.bonus}`);
console.log(`Total Annual Compensation: $${this.getAnnualSalary()}`);
}
}
// 创建父类和子类的实例
const employee = new Employee("John Doe", "Developer", 5000);
const manager = new Manager("Jane Smith", "Engineering Manager", 8000, "Engineering", 15000);
// 调用父类的方法
employee.displayInfo();
console.log(`Annual Salary: $${employee.getAnnualSalary()}`);
/* 输出:
Name: John Doe, Position: Developer, Monthly Salary: $5000
Annual Salary: $60000
*/
// 调用子类重写的方法
manager.displayInfo();
/* 输出:
Name: Jane Smith, Position: Engineering Manager, Monthly Salary: $8000
Department: Engineering, Annual Bonus: $15000
Total Annual Compensation: $111000
*/抽象类和接口是TypeScript中用于定义类型约束和抽象行为的重要机制。它们可以帮助我们更好地组织代码,提高代码的可维护性和可扩展性。
抽象类是一种不能直接实例化的类,它只能作为其他类的基类。抽象类可以包含抽象方法(没有实现的方法)和非抽象方法(有实现的方法)。子类必须实现父类中的所有抽象方法。
基本语法:
abstract class 抽象类名 {
// 非抽象方法
方法名(): 返回类型 {
// 方法体
}
// 抽象方法(没有实现)
abstract 抽象方法名(): 返回类型;
}
class 子类名 extends 抽象类名 {
// 必须实现父类中的所有抽象方法
抽象方法名(): 返回类型 {
// 方法体
}
}示例:
// 定义一个抽象类
abstract class Vehicle {
protected brand: string;
protected model: string;
protected year: number;
constructor(brand: string, model: string, year: number) {
this.brand = brand;
this.model = model;
this.year = year;
}
// 非抽象方法
displayInfo(): void {
console.log(`${this.year} ${this.brand} ${this.model}`);
}
// 抽象方法(没有实现)
abstract startEngine(): void;
abstract stopEngine(): void;
// 抽象方法可以有参数
abstract accelerate(speed: number): void;
}
// 定义继承自抽象类的子类,必须实现所有抽象方法
class Car extends Vehicle {
private fuelLevel: number;
constructor(brand: string, model: string, year: number) {
super(brand, model, year);
this.fuelLevel = 100;
}
// 实现抽象方法
startEngine(): void {
console.log(`${this.brand} ${this.model} engine started.`);
}
// 实现抽象方法
stopEngine(): void {
console.log(`${this.brand} ${this.model} engine stopped.`);
}
// 实现抽象方法
accelerate(speed: number): void {
console.log(`${this.brand} ${this.model} accelerating to ${speed} km/h.`);
// 模拟油耗
this.fuelLevel -= speed / 10;
console.log(`Fuel level: ${this.fuelLevel.toFixed(2)}%`);
}
// 子类特有的方法
refuel(amount: number): void {
this.fuelLevel = Math.min(100, this.fuelLevel + amount);
console.log(`${this.brand} ${this.model} refueled. Fuel level: ${this.fuelLevel.toFixed(2)}%`);
}
}
// 定义另一个继承自抽象类的子类
class ElectricCar extends Vehicle {
private batteryLevel: number;
constructor(brand: string, model: string, year: number) {
super(brand, model, year);
this.batteryLevel = 100;
}
// 实现抽象方法
startEngine(): void {
console.log(`${this.brand} ${this.model} electric motor started silently.`);
}
// 实现抽象方法
stopEngine(): void {
console.log(`${this.brand} ${this.model} electric motor stopped.`);
}
// 实现抽象方法
accelerate(speed: number): void {
console.log(`${this.brand} ${this.model} accelerating to ${speed} km/h.`);
// 模拟电池消耗
this.batteryLevel -= speed / 15;
console.log(`Battery level: ${this.batteryLevel.toFixed(2)}%`);
}
// 子类特有的方法
charge(amount: number): void {
this.batteryLevel = Math.min(100, this.batteryLevel + amount);
console.log(`${this.brand} ${this.model} charging. Battery level: ${this.batteryLevel.toFixed(2)}%`);
}
}
// 不能直接实例化抽象类
// const vehicle = new Vehicle("Toyota", "Corolla", 2022); // 编译错误
// 创建子类的实例
const car = new Car("Toyota", "Camry", 2022);
const electricCar = new ElectricCar("Tesla", "Model 3", 2023);
// 调用继承的方法
car.displayInfo();
electricCar.displayInfo();
// 调用实现的抽象方法
car.startEngine();
car.accelerate(60);
car.stopEngine();
console.log("\n");
electricCar.startEngine();
electricCar.accelerate(80);
electricCar.stopEngine();
// 调用子类特有的方法
car.refuel(30);
electricCar.charge(50);接口是一种用于定义对象的结构和类型的机制。接口可以定义对象应该具有的属性和方法,但不能包含方法的实现。在TypeScript中,我们可以使用interface关键字来定义接口。
基本语法:
interface 接口名 {
// 属性声明
属性名: 类型;
// 方法声明
方法名(参数: 类型): 返回类型;
}
// 类实现接口
class 类名 implements 接口名 {
// 实现接口中定义的所有属性和方法
}示例:
// 定义一个接口
interface Shape {
name: string;
// 方法声明(没有实现)
calculateArea(): number;
calculatePerimeter(): number;
}
// 类实现接口,必须实现接口中定义的所有属性和方法
class Circle implements Shape {
name: string;
radius: number;
constructor(name: string, radius: number) {
this.name = name;
this.radius = radius;
}
// 实现接口中的方法
calculateArea(): number {
return Math.PI * this.radius * this.radius;
}
// 实现接口中的方法
calculatePerimeter(): number {
return 2 * Math.PI * this.radius;
}
}
class Rectangle implements Shape {
name: string;
width: number;
height: number;
constructor(name: string, width: number, height: number) {
this.name = name;
this.width = width;
this.height = height;
}
// 实现接口中的方法
calculateArea(): number {
return this.width * this.height;
}
// 实现接口中的方法
calculatePerimeter(): number {
return 2 * (this.width + this.height);
}
}
// 使用接口作为类型注解
function printShapeInfo(shape: Shape): void {
console.log(`Shape: ${shape.name}`);
console.log(`Area: ${shape.calculateArea().toFixed(2)}`);
console.log(`Perimeter: ${shape.calculatePerimeter().toFixed(2)}`);
console.log("------------------------");
}
// 创建实现了接口的类的实例
const circle = new Circle("Circle", 5);
const rectangle = new Rectangle("Rectangle", 4, 6);
// 调用函数,传递实现了接口的类的实例
printShapeInfo(circle);
printShapeInfo(rectangle);
/* 输出:
Shape: Circle
Area: 78.54
Perimeter: 31.42
------------------------
Shape: Rectangle
Area: 24.00
Perimeter: 20.00
------------------------
*/
// 接口可以用于对象字面量
const square: Shape = {
name: "Square",
calculateArea: function(): number {
return 5 * 5;
},
calculatePerimeter: function(): number {
return 4 * 5;
}
};
printShapeInfo(square);
/* 输出:
Shape: Square
Area: 25.00
Perimeter: 20.00
------------------------
*/接口可以继承其他接口,这允许我们创建更具体的接口。在TypeScript中,我们可以使用extends关键字来实现接口继承。
基本语法:
interface 父接口名 {
// 父接口的属性和方法
}
interface 子接口名 extends 父接口名 {
// 子接口特有的属性和方法
}示例:
// 定义一个基础接口
interface Person {
id: number;
name: string;
email: string;
getInfo(): string;
}
// 定义继承自Person的接口
interface Employee extends Person {
employeeId: number;
position: string;
department: string;
salary: number;
getEmployeeInfo(): string;
}
// 定义继承自Employee的接口
interface Manager extends Employee {
teamSize: number;
hasBudgetApproval: boolean;
getManagerInfo(): string;
}
// 类实现最具体的接口,必须实现所有继承的属性和方法
class SeniorManager implements Manager {
// Person接口的属性
id: number;
name: string;
email: string;
// Employee接口的属性
employeeId: number;
position: string;
department: string;
salary: number;
// Manager接口的属性
teamSize: number;
hasBudgetApproval: boolean;
constructor(
id: number,
name: string,
email: string,
employeeId: number,
position: string,
department: string,
salary: number,
teamSize: number,
hasBudgetApproval: boolean
) {
this.id = id;
this.name = name;
this.email = email;
this.employeeId = employeeId;
this.position = position;
this.department = department;
this.salary = salary;
this.teamSize = teamSize;
this.hasBudgetApproval = hasBudgetApproval;
}
// 实现Person接口的方法
getInfo(): string {
return `ID: ${this.id}, Name: ${this.name}, Email: ${this.email}`;
}
// 实现Employee接口的方法
getEmployeeInfo(): string {
return `${this.getInfo()}, Employee ID: ${this.employeeId}, Position: ${this.position}, Department: ${this.department}, Salary: $${this.salary}`;
}
// 实现Manager接口的方法
getManagerInfo(): string {
return `${this.getEmployeeInfo()}, Team Size: ${this.teamSize}, Budget Approval: ${this.hasBudgetApproval ? 'Yes' : 'No'}`;
}
}
// 创建实现了接口的类的实例
const manager = new SeniorManager(
1,
"Jane Smith",
"jane.smith@example.com",
1001,
"Senior Engineering Manager",
"Engineering",
150000,
20,
true
);
// 调用实现的方法
console.log(manager.getInfo());
console.log(manager.getEmployeeInfo());
console.log(manager.getManagerInfo());
// 使用接口作为类型注解
function printPersonInfo(person: Person): void {
console.log(person.getInfo());
}
function printEmployeeInfo(employee: Employee): void {
console.log(employee.getEmployeeInfo());
}
function printManagerInfo(manager: Manager): void {
console.log(manager.getManagerInfo());
}
// 由于接口继承关系,我们可以将Manager类型的对象传递给接受Person或Employee类型的函数
printPersonInfo(manager);
printEmployeeInfo(manager);
printManagerInfo(manager);抽象类和接口在TypeScript中有一些相似之处,但也有一些重要的区别:
示例:
// 抽象类示例
abstract class AbstractAnimal {
// 可以有构造函数
constructor(protected name: string) {}
// 可以有实现的方法
eat(): void {
console.log(`${this.name} is eating.`);
}
// 可以有抽象方法(没有实现)
abstract makeSound(): void;
}
// 接口示例
interface InterfaceAnimal {
// 不能有构造函数
// constructor(name: string); // 编译错误
// 不能有访问修饰符
// protected name: string; // 编译错误
// 不能有实现的方法
// eat(): void { // 编译错误
// console.log(`${this.name} is eating.`);
// }
// 只能有方法声明
eat(): void;
makeSound(): void;
}
// 类可以实现多个接口
interface Flyable {
fly(): void;
}
interface Swimmable {
swim(): void;
}
// 一个类只能继承一个抽象类,但可以实现多个接口
class Duck extends AbstractAnimal implements Flyable, Swimmable {
constructor(name: string) {
super(name);
}
// 必须实现抽象类中的抽象方法
makeSound(): void {
console.log(`${this.name} quacks: Quack! Quack!`);
}
// 必须实现接口中的方法
fly(): void {
console.log(`${this.name} is flying.`);
}
// 必须实现接口中的方法
swim(): void {
console.log(`${this.name} is swimming.`);
}
}
// 创建实例
const duck = new Duck("Donald");
// 调用继承的方法
console.log(duck.name); // 编译错误:name是protected的,只能在类内部和子类中访问
console.log((duck as any).name); // 输出: Donald(不推荐这样做)
duck.eat(); // 输出: Donald is eating.
duck.makeSound(); // 输出: Donald quacks: Quack! Quack!
duck.fly(); // 输出: Donald is flying.
duck.swim(); // 输出: Donald is swimming.访问修饰符用于控制类中属性和方法的访问权限。在TypeScript中,有四种访问修饰符:public、private、protected和readonly。
public修饰符表示属性或方法是公有的,可以在任何地方访问。默认情况下,类的属性和方法都是public的。
示例:
class Person {
// public修饰符(可以省略)
public name: string;
// 默认是public的
age: number;
// 构造函数中的public参数属性
constructor(public email: string, name: string, age: number) {
this.name = name;
this.age = age;
}
// public方法(可以省略)
public greet(): string {
return `Hello, my name is ${this.name}.`;
}
// 默认是public的方法
getInfo(): string {
return `${this.name}, ${this.age} years old, ${this.email}`;
}
}
const person = new Person("john.doe@example.com", "John Doe", 30);
// 可以在任何地方访问public属性和方法
console.log(person.name); // 输出: John Doe
console.log(person.age); // 输出: 30
console.log(person.email); // 输出: john.doe@example.com
console.log(person.greet()); // 输出: Hello, my name is John Doe.
console.log(person.getInfo()); // 输出: John Doe, 30 years old, john.doe@example.com
// 可以修改public属性
person.name = "Jane Smith";
person.age = 25;
person.email = "jane.smith@example.com";
console.log(person.getInfo()); // 输出: Jane Smith, 25 years old, jane.smith@example.comprivate修饰符表示属性或方法是私有的,只能在类的内部访问,不能在类的外部或子类中访问。
示例:
class BankAccount {
// public属性
public accountNumber: string;
// private属性
private balance: number;
// private方法
private logTransaction(description: string): void {
console.log(`Transaction: ${description}, New Balance: $${this.balance}`);
}
constructor(accountNumber: string, initialBalance: number) {
this.accountNumber = accountNumber;
this.balance = initialBalance;
this.logTransaction(`Initial deposit of $${initialBalance}`);
}
// public方法,可以访问private属性和方法
deposit(amount: number): void {
if (amount > 0) {
this.balance += amount;
this.logTransaction(`Deposit of $${amount}`);
} else {
console.error("Deposit amount must be positive");
}
}
// public方法,可以访问private属性和方法
withdraw(amount: number): boolean {
if (amount > 0 && amount <= this.balance) {
this.balance -= amount;
this.logTransaction(`Withdrawal of $${amount}`);
return true;
} else {
console.error("Invalid withdrawal amount or insufficient funds");
return false;
}
}
// public方法,可以访问private属性
getBalance(): number {
return this.balance;
}
}
// 创建BankAccount实例
const account = new BankAccount("1234567890", 1000);
// 可以访问public属性
console.log(account.accountNumber); // 输出: 1234567890
// 可以调用public方法
account.deposit(500); // 输出: Transaction: Deposit of $500, New Balance: $1500
console.log(account.getBalance()); // 输出: 1500
account.withdraw(200); // 输出: Transaction: Withdrawal of $200, New Balance: $1300
console.log(account.getBalance()); // 输出: 1300
// 不能直接访问private属性和方法
// console.log(account.balance); // 编译错误
// account.logTransaction("Test"); // 编译错误
// 定义继承自BankAccount的子类
class SavingsAccount extends BankAccount {
constructor(accountNumber: string, initialBalance: number) {
super(accountNumber, initialBalance);
}
// 子类不能访问父类的private属性和方法
// addInterest(rate: number): void {
// const interest = this.balance * rate; // 编译错误
// this.deposit(interest);
// }
}protected修饰符表示属性或方法是受保护的,只能在类的内部或子类中访问,不能在类的外部访问。
示例:
class Person {
// public属性
public name: string;
// protected属性
protected age: number;
// protected方法
protected validateAge(newAge: number): boolean {
return newAge >= 0 && newAge <= 120;
}
constructor(name: string, age: number) {
this.name = name;
// 在类内部可以访问protected属性和方法
if (this.validateAge(age)) {
this.age = age;
} else {
this.age = 0;
console.error("Invalid age");
}
}
// public方法,可以访问protected属性和方法
getInfo(): string {
return `${this.name}, ${this.age} years old`;
}
}
// 定义继承自Person的子类
class Employee extends Person {
private employeeId: number;
private position: string;
constructor(name: string, age: number, employeeId: number, position: string) {
super(name, age);
this.employeeId = employeeId;
this.position = position;
}
// 子类可以访问父类的protected属性和方法
updateAge(newAge: number): void {
if (this.validateAge(newAge)) {
this.age = newAge;
} else {
console.error("Invalid age");
}
}
// 子类的public方法
getEmployeeInfo(): string {
// 在子类中可以访问父类的protected属性
return `${this.getInfo()}, Employee ID: ${this.employeeId}, Position: ${this.position}`;
}
}
// 创建Person实例
const person = new Person("John Doe", 30);
// 可以访问public属性和方法
console.log(person.name); // 输出: John Doe
console.log(person.getInfo()); // 输出: John Doe, 30 years old
// 不能直接访问protected属性和方法
// console.log(person.age); // 编译错误
// person.validateAge(35); // 编译错误
// 创建Employee实例
const employee = new Employee("Jane Smith", 25, 1001, "Developer");
// 可以访问public属性和方法
console.log(employee.name); // 输出: Jane Smith
console.log(employee.getInfo()); // 输出: Jane Smith, 25 years old
console.log(employee.getEmployeeInfo()); // 输出: Jane Smith, 25 years old, Employee ID: 1001, Position: Developer
// 调用子类的方法,该方法可以访问父类的protected属性和方法
employee.updateAge(26);
console.log(employee.getInfo()); // 输出: Jane Smith, 26 years old
// 不能直接访问protected属性和方法
// console.log(employee.age); // 编译错误
// employee.validateAge(35); // 编译错误readonly修饰符表示属性是只读的,只能在声明时或构造函数中初始化,之后不能修改。
示例:
class Product {
// readonly属性,在声明时初始化
readonly id: string = Math.random().toString(36).substr(2, 9);
// readonly属性,在构造函数中初始化
readonly createdAt: Date;
// public属性
name: string;
price: number;
constructor(name: string, price: number) {
this.name = name;
this.price = price;
this.createdAt = new Date();
}
// 不能修改readonly属性
// updateId(newId: string): void {
// this.id = newId; // 编译错误
// }
// 可以修改public属性
updatePrice(newPrice: number): void {
if (newPrice > 0) {
this.price = newPrice;
}
}
// 可以访问readonly属性
getInfo(): string {
return `ID: ${this.id}, Name: ${this.name}, Price: $${this.price}, Created: ${this.createdAt.toLocaleDateString()}`;
}
}
// 创建Product实例
const product = new Product("Laptop", 999.99);
// 可以访问readonly属性
console.log(product.id); // 输出: 随机生成的ID
console.log(product.createdAt); // 输出: 当前日期和时间
console.log(product.name); // 输出: Laptop
console.log(product.price); // 输出: 999.99
// 可以修改public属性
product.name = "Gaming Laptop";
product.updatePrice(1299.99);
// 不能修改readonly属性
// product.id = "new-id";
// product.createdAt = new Date(2020, 0, 1);
console.log(product.getInfo());
// readonly和访问修饰符可以一起使用
class User {
readonly id: number;
public name: string;
private readonly createdAt: Date;
protected readonly lastLoginAt: Date;
constructor(id: number, name: string) {
this.id = id;
this.name = name;
this.createdAt = new Date();
this.lastLoginAt = new Date();
}
login(): void {
// 不能修改readonly属性
// this.lastLoginAt = new Date(); // 编译错误
console.log(`${this.name} logged in.`);
}
}静态成员是属于类本身而不是类实例的属性和方法。单例模式是一种常用的设计模式,它确保一个类只有一个实例,并提供一个全局访问点。
在TypeScript中,我们可以使用static关键字来定义静态属性和方法。静态成员属于类本身,而不是类的实例,因此可以直接通过类名访问,而不需要创建类的实例。
基本语法:
class 类名 {
// 静态属性
static 静态属性名: 类型 = 默认值;
// 静态方法
static 静态方法名(参数: 类型): 返回类型 {
// 方法体
// 可以访问静态属性
return this.静态属性名;
}
// 实例属性
实例属性名: 类型;
// 实例方法
实例方法名(参数: 类型): 返回类型 {
// 可以访问实例属性和静态属性/方法
this.实例属性名;
类名.静态属性名;
类名.静态方法名(参数);
}
}
// 访问静态属性和方法
类名.静态属性名;
类名.静态方法名(参数);示例:
class MathUtils {
// 静态属性
static PI: number = 3.14159265359;
static MAX_NUMBER: number = 1.7976931348623157e+308;
static MIN_NUMBER: number = 5e-324;
// 静态方法
static add(a: number, b: number): number {
return a + b;
}
static subtract(a: number, b: number): number {
return a - b;
}
static multiply(a: number, b: number): number {
return a * b;
}
static divide(a: number, b: number): number {
if (b === 0) {
throw new Error("Division by zero is not allowed");
}
return a / b;
}
static calculateCircleArea(radius: number): number {
return this.PI * radius * radius; // 在静态方法中使用this访问静态属性
}
static calculateCircleCircumference(radius: number): number {
return 2 * this.PI * radius;
}
}
// 直接通过类名访问静态属性和方法,不需要创建实例
console.log(MathUtils.PI); // 输出: 3.14159265359
console.log(MathUtils.MAX_NUMBER); // 输出: 1.7976931348623157e+308
console.log(MathUtils.add(5, 3)); // 输出: 8
console.log(MathUtils.subtract(10, 4)); // 输出: 6
console.log(MathUtils.multiply(6, 7)); // 输出: 42
console.log(MathUtils.divide(20, 5)); // 输出: 4
console.log(MathUtils.calculateCircleArea(5)); // 输出: 78.53981633975
console.log(MathUtils.calculateCircleCircumference(5)); // 输出: 31.4159265359
// 创建实例(虽然可以创建,但通常不需要,因为所有功能都是静态的)
const mathUtils = new MathUtils();
// 实例也可以访问静态属性和方法,但不推荐这样做
console.log(mathUtils.PI); // 输出: 3.14159265359
console.log(mathUtils.calculateCircleArea(3)); // 输出: 28.27433388231
// 另一个示例:计数器类
class Counter {
// 静态属性,用于跟踪所有实例的总数
private static instanceCount: number = 0;
// 实例属性
private count: number = 0;
constructor() {
// 在构造函数中更新静态属性
Counter.instanceCount++;
}
// 实例方法
increment(): void {
this.count++;
}
decrement(): void {
this.count--;
}
getCount(): number {
return this.count;
}
// 静态方法,用于获取所有实例的总数
static getInstanceCount(): number {
return Counter.instanceCount;
}
// 静态方法,用于重置实例计数器
static resetInstanceCount(): void {
Counter.instanceCount = 0;
}
}
// 创建多个Counter实例
const counter1 = new Counter();
const counter2 = new Counter();
const counter3 = new Counter();
// 使用实例方法
counter1.increment();
counter1.increment();
counter2.increment();
console.log(counter1.getCount()); // 输出: 2
console.log(counter2.getCount()); // 输出: 1
console.log(counter3.getCount()); // 输出: 0
// 使用静态方法获取所有实例的总数
console.log(Counter.getInstanceCount()); // 输出: 3
// 重置计数器
Counter.resetInstanceCount();
console.log(Counter.getInstanceCount()); // 输出: 0单例模式是一种常用的设计模式,它确保一个类只有一个实例,并提供一个全局访问点。在TypeScript中,我们可以使用静态属性和方法来实现单例模式。
基本语法:
class Singleton {
// 静态属性,用于存储唯一实例
private static instance: Singleton;
// 私有构造函数,防止外部创建实例
private constructor() {
// 初始化代码
}
// 静态方法,用于获取唯一实例
static getInstance(): Singleton {
if (!Singleton.instance) {
Singleton.instance = new Singleton();
}
return Singleton.instance;
}
// 实例方法
doSomething(): void {
// 方法实现
}
}
// 获取单例实例
const instance1 = Singleton.getInstance();
const instance2 = Singleton.getInstance();
// 验证是否是同一个实例
console.log(instance1 === instance2); // 输出: true
// 不能直接创建实例
// const instance = new Singleton(); // 编译错误示例:
// 实现一个日志管理器单例
class Logger {
// 私有静态属性,用于存储唯一实例
private static instance: Logger;
// 日志级别
private logLevel: 'debug' | 'info' | 'warn' | 'error' = 'info';
// 日志记录
private logs: string[] = [];
// 私有构造函数,防止外部创建实例
private constructor() {
console.log('Logger instance created');
}
// 静态方法,用于获取唯一实例
static getInstance(): Logger {
if (!Logger.instance) {
Logger.instance = new Logger();
}
return Logger.instance;
}
// 设置日志级别
setLogLevel(level: 'debug' | 'info' | 'warn' | 'error'): void {
this.logLevel = level;
this.log(`Log level set to ${level}`, 'debug');
}
// 调试日志
debug(message: string): void {
if (this.logLevel === 'debug') {
this.log(message, 'debug');
}
}
// 信息日志
info(message: string): void {
if (this.logLevel === 'debug' || this.logLevel === 'info') {
this.log(message, 'info');
}
}
// 警告日志
warn(message: string): void {
if (this.logLevel === 'debug' || this.logLevel === 'info' || this.logLevel === 'warn') {
this.log(message, 'warn');
}
}
// 错误日志
error(message: string): void {
this.log(message, 'error');
}
// 私有方法,用于记录日志
private log(message: string, level: string): void {
const timestamp = new Date().toISOString();
const logMessage = `[${timestamp}] [${level.toUpperCase()}] ${message}`;
// 添加到日志记录中
this.logs.push(logMessage);
// 输出到控制台
console.log(logMessage);
}
// 获取所有日志
getAllLogs(): string[] {
return [...this.logs]; // 返回日志的副本,避免外部修改
}
// 清除所有日志
clearLogs(): void {
this.logs = [];
this.log('Logs cleared', 'debug');
}
}
// 获取Logger单例实例
const logger1 = Logger.getLogger();
const logger2 = Logger.getLogger();
// 验证是否是同一个实例
console.log(logger1 === logger2); // 输出: true
// 使用Logger记录日志
logger1.info('Application started');
logger1.warn('Disk space is running low');
logger1.error('Failed to connect to database');
// 设置日志级别
logger1.setLogLevel('debug');
logger1.debug('This is a debug message');
// 由于是单例,logger2和logger1是同一个实例
logger2.info('This message is logged by logger2');
// 获取所有日志
const logs = logger1.getAllLogs();
console.log('All logs:', logs);
// 清除所有日志
logger1.clearLogs();
// 另一个示例:配置管理器单例
class ConfigManager {
private static instance: ConfigManager;
private config: { [key: string]: any } = {};
private constructor() {
// 初始化默认配置
this.config = {
apiUrl: 'https://api.example.com',
timeout: 5000,
retryCount: 3,
debug: false
};
}
static getInstance(): ConfigManager {
if (!ConfigManager.instance) {
ConfigManager.instance = new ConfigManager();
}
return ConfigManager.instance;
}
// 获取配置项
get(key: string): any {
return this.config[key];
}
// 设置配置项
set(key: string, value: any): void {
this.config[key] = value;
}
// 获取所有配置
getAll(): { [key: string]: any } {
return { ...this.config }; // 返回配置的副本
}
// 加载配置
load(config: { [key: string]: any }): void {
this.config = { ...this.config, ...config };
}
}
// 获取ConfigManager单例实例
const configManager = ConfigManager.getInstance();
// 获取配置项
console.log(configManager.get('apiUrl')); // 输出: https://api.example.com
console.log(configManager.get('timeout')); // 输出: 5000
// 设置配置项
configManager.set('debug', true);
console.log(configManager.get('debug')); // 输出: true
// 加载新配置
configManager.load({
apiUrl: 'https://api.dev.example.com',
timeout: 10000
});
console.log(configManager.get('apiUrl')); // 输出: https://api.dev.example.com
console.log(configManager.get('timeout')); // 输出: 10000
console.log(configManager.get('debug')); // 输出: true(保留之前设置的值)
// 获取所有配置
const allConfig = configManager.getAll();
console.log('All config:', allConfig);泛型是TypeScript中的一个重要特性,它允许我们编写可以处理不同类型数据的代码,而不必为每种类型编写单独的代码。泛型类和泛型接口是使用泛型的常见方式。
泛型类是指可以接受类型参数的类。在TypeScript中,我们可以使用尖括号<>来定义泛型类。
基本语法:
class 类名<T> {
// 使用泛型类型参数的属性
private 数据: T;
constructor(数据: T) {
this.数据 = 数据;
}
// 使用泛型类型参数的方法
方法名(): T {
return this.数据;
}
// 泛型方法
泛型方法名<U>(参数: U): U {
return 参数;
}
}
// 创建泛型类的实例,指定具体类型
const 实例名 = new 类名<具体类型>(参数);示例:
// 定义一个简单的泛型类
class Box<T> {
private content: T;
constructor(content: T) {
this.content = content;
}
getContent(): T {
return this.content;
}
setContent(content: T): void {
this.content = content;
}
// 泛型方法
map<U>(transform: (value: T) => U): Box<U> {
return new Box<U>(transform(this.content));
}
}
// 创建泛型类的实例,指定具体类型
const numberBox = new Box<number>(42);
const stringBox = new Box<string>("Hello, TypeScript!");
const booleanBox = new Box<boolean>(true);
// 使用泛型类的方法
console.log(numberBox.getContent()); // 输出: 42
console.log(stringBox.getContent()); // 输出: Hello, TypeScript!
console.log(booleanBox.getContent()); // 输出: true
// 修改内容
numberBox.setContent(100);
console.log(numberBox.getContent()); // 输出: 100
// 使用泛型方法
const stringFromNumber = numberBox.map(value => `The answer is: ${value}`);
console.log(stringFromNumber.getContent()); // 输出: The answer is: 100
const lengthBox = stringBox.map(value => value.length);
console.log(lengthBox.getContent()); // 输出: 18
// 可以使用类型推断,不需要显式指定类型
const inferredBox = new Box("TypeScript"); // TypeScript会推断出类型为Box<string>
console.log(inferredBox.getContent()); // 输出: 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];
}
// 检查栈是否为空
isEmpty(): boolean {
return this.items.length === 0;
}
// 获取栈的大小
size(): number {
return this.items.length;
}
// 清空栈
clear(): void {
this.items = [];
}
// 遍历栈中的所有元素
forEach(callback: (item: T) => void): void {
// 从栈顶到栈底遍历
for (let i = this.items.length - 1; i >= 0; i--) {
callback(this.items[i]);
}
}
}
// 创建一个数字类型的栈
const numberStack = new Stack<number>();
numberStack.push(1);
numberStack.push(2);
numberStack.push(3);
console.log(numberStack.size()); // 输出: 3
console.log(numberStack.peek()); // 输出: 3
console.log(numberStack.pop()); // 输出: 3
console.log(numberStack.size()); // 输出: 2
// 遍历栈中的元素
console.log("Stack contents (from top to bottom):");
numberStack.forEach(item => console.log(item));
// 输出:
// Stack contents (from top to bottom):
// 2
// 1
// 创建一个字符串类型的栈
const stringStack = new Stack<string>();
stringStack.push("TypeScript");
stringStack.push("JavaScript");
stringStack.push("Node.js");
console.log(stringStack.size()); // 输出: 3
console.log(stringStack.peek()); // 输出: Node.js
// 清空栈
stringStack.clear();
console.log(stringStack.isEmpty()); // 输出: true有时候,我们希望泛型类型参数遵循某些约束,而不是可以是任何类型。在TypeScript中,我们可以使用泛型约束来限制泛型类型参数的范围。
基本语法:
// 定义一个接口,用于约束泛型类型参数
interface 接口名 {
属性名: 类型;
方法名(): 返回类型;
}
// 使用extends关键字应用约束
class 类名<T extends 接口名> {
// 类的实现
}示例:
// 定义一个接口,用于约束泛型类型参数
interface Printable {
print(): void;
}
// 定义一个泛型类,应用Printable约束
class Printer<T extends Printable> {
printAll(items: T[]): void {
for (const item of items) {
item.print(); // 可以安全地调用print方法,因为T被约束为Printable类型
}
}
}
// 定义一些实现了Printable接口的类
class Book implements Printable {
constructor(private title: string, private author: string) {}
print(): void {
console.log(`Book: ${this.title} by ${this.author}`);
}
}
class Document implements Printable {
constructor(private name: string, private content: string) {}
print(): void {
console.log(`Document: ${this.name}`);
console.log(`Content: ${this.content.substring(0, 50)}...`);
}
}
class Report implements Printable {
constructor(private title: string, private date: Date) {}
print(): void {
console.log(`Report: ${this.title}`);
console.log(`Date: ${this.date.toLocaleDateString()}`);
}
}
// 创建Printer实例
const printer = new Printer<Printable>(); // 可以使用接口类型作为泛型参数
// 创建一些实现了Printable接口的对象
const book1 = new Book("TypeScript Basics", "John Doe");
const book2 = new Book("Advanced TypeScript", "Jane Smith");
const doc1 = new Document("Meeting Notes", "Discussed TypeScript generics and interfaces.");
const report1 = new Report("Monthly Sales", new Date());
// 创建一个混合类型的数组
const printableItems: Printable[] = [book1, doc1, book2, report1];
// 使用Printer打印所有可打印的项目
printer.printAll(printableItems);
// 另一个示例:带有约束的缓存类
interface Cacheable {
id: string;
}
class Cache<T extends Cacheable> {
private items: Map<string, T> = new Map();
// 添加项目到缓存
add(item: T): void {
this.items.set(item.id, item);
}
// 从缓存中获取项目
get(id: string): T | undefined {
return this.items.get(id);
}
// 从缓存中删除项目
remove(id: string): boolean {
return this.items.delete(id);
}
// 检查缓存中是否存在项目
has(id: string): boolean {
return this.items.has(id);
}
// 获取缓存的大小
size(): number {
return this.items.size;
}
// 清空缓存
clear(): void {
this.items.clear();
}
}
// 定义一些实现了Cacheable接口的类
class User implements Cacheable {
id: string;
name: string;
email: string;
constructor(id: string, name: string, email: string) {
this.id = id;
this.name = name;
this.email = email;
}
}
class Product implements Cacheable {
id: string;
name: string;
price: number;
constructor(id: string, name: string, price: number) {
this.id = id;
this.name = name;
this.price = price;
}
}
// 创建User类型的缓存
const userCache = new Cache<User>();
// 添加用户到缓存
const user1 = new User("1", "John Doe", "john.doe@example.com");
const user2 = new User("2", "Jane Smith", "jane.smith@example.com");
userCache.add(user1);
userCache.add(user2);
console.log(`User cache size: ${userCache.size()}`); // 输出: User cache size: 2
// 从缓存中获取用户
const retrievedUser = userCache.get("1");
if (retrievedUser) {
console.log(`Retrieved user: ${retrievedUser.name}, ${retrievedUser.email}`);
// 输出: Retrieved user: John Doe, john.doe@example.com
}
// 创建Product类型的缓存
const productCache = new Cache<Product>();
// 添加产品到缓存
const product1 = new Product("p1", "Laptop", 999.99);
const product2 = new Product("p2", "Phone", 499.99);
productCache.add(product1);
productCache.add(product2);
console.log(`Product cache size: ${productCache.size()}`); // 输出: Product cache size: 2
// 检查产品是否在缓存中
console.log(`Product p1 exists: ${productCache.has("p1")}`); // 输出: Product p1 exists: true
console.log(`Product p3 exists: ${productCache.has("p3")}`); // 输出: Product p3 exists: false泛型接口是指可以接受类型参数的接口。在TypeScript中,我们也可以使用尖括号<>来定义泛型接口。
基本语法:
interface 接口名<T> {
属性名: T;
方法名(参数: T): T;
}
// 类实现泛型接口
class 类名<T> implements 接口名<T> {
// 类的实现
}
// 接口继承泛型接口
interface 子接口名<T, U> extends 接口名<T> {
// 子接口的属性和方法
}示例:
// 定义一个泛型接口
interface Container<T> {
value: T;
getValue(): T;
setValue(value: T): void;
}
// 实现泛型接口的类
class SimpleContainer<T> implements Container<T> {
value: T;
constructor(value: T) {
this.value = value;
}
getValue(): T {
return this.value;
}
setValue(value: T): void {
this.value = value;
}
}
// 创建泛型接口的实例
const numberContainer: Container<number> = new SimpleContainer<number>(42);
const stringContainer: Container<string> = new SimpleContainer<string>("TypeScript");
const booleanContainer: Container<boolean> = new SimpleContainer<boolean>(true);
console.log(numberContainer.getValue()); // 输出: 42
console.log(stringContainer.getValue()); // 输出: TypeScript
console.log(booleanContainer.getValue()); // 输出: true
// 修改值
numberContainer.setValue(100);
console.log(numberContainer.getValue()); // 输出: 100
// 另一个示例:泛型回调接口
interface Callback<T, U> {
(input: T): U;
}
// 使用泛型回调接口的函数
function mapArray<T, U>(array: T[], callback: Callback<T, U>): U[] {
const result: U[] = [];
for (const item of array) {
result.push(callback(item));
}
return result;
}
// 使用示例
const numbers = [1, 2, 3, 4, 5];
// 将数字数组映射为字符串数组
const numberStrings = mapArray<number, string>(numbers, num => `Number: ${num}`);
console.log(numberStrings); // 输出: [ 'Number: 1', 'Number: 2', 'Number: 3', 'Number: 4', 'Number: 5' ]
// 将数字数组映射为它们的平方
const squares = mapArray<number, number>(numbers, num => num * num);
console.log(squares); // 输出: [ 1, 4, 9, 16, 25 ]
// 将数字数组映射为布尔值(检查是否为偶数)
const evenFlags = mapArray<number, boolean>(numbers, num => num % 2 === 0);
console.log(evenFlags); // 输出: [ false, true, false, true, false ]
// 泛型接口继承示例
interface Reader<T> {
read(): T;
}
interface Writer<T> {
write(value: T): void;
}
// 继承两个泛型接口,可以使用不同的类型参数
interface ReadWrite<T, U> extends Reader<T>, Writer<U> {
clear(): void;
}
// 实现继承了泛型接口的接口
class MemoryStorage<T, U> implements ReadWrite<T, U> {
private data: T;
constructor(initialData: T) {
this.data = initialData;
}
read(): T {
return this.data;
}
write(value: U): void {
// 注意:这里我们假设U和T是兼容的类型
// 在实际应用中,可能需要添加类型转换或验证
this.data = value as unknown as T;
}
clear(): void {
// 在实际应用中,这里可能需要更复杂的清除逻辑
this.data = {} as T;
}
}
// 创建MemoryStorage实例
const storage = new MemoryStorage<string, number>("Initial data");
console.log(storage.read()); // 输出: Initial data
// 写入新值(注意:这里我们在write方法中进行了类型转换)
storage.write(42);
console.log(storage.read()); // 输出: 42
// 清除存储
storage.clear();
console.log(storage.read()); // 输出: {}TypeScript提供了一些内置的泛型工具类型,可以帮助我们更方便地操作类型。这些工具类型位于TypeScript的标准库中,我们可以直接使用它们。
常用的泛型工具类型包括:
示例:
// 定义一个接口
interface User {
id: number;
name: string;
email: string;
age?: number;
address?: string;
}
// 使用Partial<T>:将所有属性变为可选
type PartialUser = Partial<User>;
const partialUser: PartialUser = {
name: "John Doe"
// 其他属性都是可选的
};
// 使用Required<T>:将所有属性变为必需
type RequiredUser = Required<User>;
// 编译错误:缺少必需的属性
// const requiredUser: RequiredUser = {
// id: 1,
// name: "John Doe",
// email: "john.doe@example.com"
// // 缺少必需的属性:age和address
// };
// 使用Readonly<T>:将所有属性变为只读
type ReadonlyUser = Readonly<User>;
const readonlyUser: ReadonlyUser = {
id: 1,
name: "John Doe",
email: "john.doe@example.com"
};
// 编译错误:不能修改只读属性
// readonlyUser.name = "Jane Smith";
// 使用Record<K, T>:创建键值对类型
type UserMap = Record<string, User>;
const userMap: UserMap = {
"user1": {
id: 1,
name: "John Doe",
email: "john.doe@example.com"
},
"user2": {
id: 2,
name: "Jane Smith",
email: "jane.smith@example.com"
}
};
// 使用Pick<T, K>:从T中选择指定的属性
type UserBasicInfo = Pick<User, "id" | "name" | "email">;
const userBasicInfo: UserBasicInfo = {
id: 1,
name: "John Doe",
email: "john.doe@example.com"
// 不能包含age和address属性
};
// 使用Omit<T, K>:从T中排除指定的属性
type UserWithoutOptional = Omit<User, "age" | "address">;
const userWithoutOptional: UserWithoutOptional = {
id: 1,
name: "John Doe",
email: "john.doe@example.com"
// 不能包含age和address属性
};
// 使用Exclude<T, U>:从T中排除可以赋值给U的类型
type Primitive = string | number | boolean | null | undefined;
type NonNullablePrimitive = Exclude<Primitive, null | undefined>;
// NonNullablePrimitive = string | number | boolean
// 使用Extract<T, U>:从T中提取可以赋值给U的类型
type StringOrNumber = Extract<Primitive, string | number>;
// StringOrNumber = string | number
// 使用ReturnType<T>:获取函数的返回类型
function getUserInfo(id: number): User {
return {
id,
name: "John Doe",
email: `john.doe${id}@example.com`
};
}
type UserInfoReturnType = ReturnType<typeof getUserInfo>;
// UserInfoReturnType = User
// 使用Parameters<T>:获取函数参数类型的元组
type GetUserInfoParams = Parameters<typeof getUserInfo>;
// GetUserInfoParams = [id: number]
// 实际应用示例:使用泛型工具类型优化代码
function updateUser(user: User, updates: Partial<User>): User {
return {
...user,
...updates
};
}
const originalUser: User = {
id: 1,
name: "John Doe",
email: "john.doe@example.com"
};
const updatedUser = updateUser(originalUser, {
name: "Jane Doe",
age: 30
});
console.log(updatedUser);
// 输出: { id: 1, name: 'Jane Doe', email: 'john.doe@example.com', age: 30 }
// 另一个示例:使用泛型工具类型创建配置验证函数
interface Config {
apiUrl: string;
timeout: number;
retryCount: number;
debug: boolean;
}
function validateConfig(config: Partial<Config>): Config {
// 设置默认值
const defaultConfig: Config = {
apiUrl: "https://api.example.com",
timeout: 5000,
retryCount: 3,
debug: false
};
// 合并默认配置和用户提供的配置
const mergedConfig: Config = {
...defaultConfig,
...config
};
// 验证必要的配置
if (!mergedConfig.apiUrl || mergedConfig.apiUrl.trim() === "") {
throw new Error("apiUrl is required");
}
if (mergedConfig.timeout <= 0) {
throw new Error("timeout must be positive");
}
if (mergedConfig.retryCount < 0) {
throw new Error("retryCount cannot be negative");
}
return mergedConfig;
}
// 使用验证函数
try {
const config = validateConfig({
apiUrl: "https://api.dev.example.com",
debug: true
});
console.log(config);
// 输出: { apiUrl: 'https://api.dev.example.com', timeout: 5000, retryCount: 3, debug: true }
} catch (error) {
console.error(error.message);
}
try {
// 尝试使用无效的配置
validateConfig({ timeout: -1 });
} catch (error) {
console.error(error.message); // 输出: timeout must be positive
}人工智能技术的发展为我们的学习提供了新的可能性。在本节中,我们将介绍如何利用AI工具来提升你的TypeScript面向对象编程学习效率。
AI代码解释器可以帮助我们理解复杂的TypeScript代码,特别是当我们遇到不熟悉的面向对象编程模式或高级特性时。
示例:
假设我们有以下复杂的TypeScript代码,使用了泛型、接口和装饰器等高级特性:
// 一个复杂的TypeScript类,使用了泛型、接口和装饰器
interface Logger {
log(message: string): void;
}
class ConsoleLogger implements Logger {
log(message: string): void {
console.log(`[LOG] ${message}`);
}
}
// 装饰器
function logMethod(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function(...args: any[]) {
console.log(`Method ${propertyKey} called with args: ${JSON.stringify(args)}`);
const result = originalMethod.apply(this, args);
console.log(`Method ${propertyKey} returned: ${JSON.stringify(result)}`);
return result;
};
return descriptor;
}
// 泛型基类
abstract class BaseRepository<T extends { id: string }> {
protected items: Map<string, T> = new Map();
protected logger: Logger;
constructor(logger: Logger) {
this.logger = logger;
}
@logMethod
add(item: T): void {
this.items.set(item.id, item);
this.logger.log(`Added item with id: ${item.id}`);
}
@logMethod
get(id: string): T | undefined {
const item = this.items.get(id);
if (item) {
this.logger.log(`Retrieved item with id: ${id}`);
} else {
this.logger.log(`Item with id: ${id} not found`);
}
return item;
}
@logMethod
update(id: string, update: Partial<T>): boolean {
const item = this.items.get(id);
if (!item) {
this.logger.log(`Failed to update: item with id: ${id} not found`);
return false;
}
const updatedItem = { ...item, ...update };
this.items.set(id, updatedItem);
this.logger.log(`Updated item with id: ${id}`);
return true;
}
@logMethod
delete(id: string): boolean {
const result = this.items.delete(id);
if (result) {
this.logger.log(`Deleted item with id: ${id}`);
} else {
this.logger.log(`Failed to delete: item with id: ${id} not found`);
}
return result;
}
@logMethod
getAll(): T[] {
const result = Array.from(this.items.values());
this.logger.log(`Retrieved all ${result.length} items`);
return result;
}
}
// 具体的用户类型
interface User {
id: string;
name: string;
email: string;
age?: number;
}
// 用户仓库类,继承自泛型基类
class UserRepository extends BaseRepository<User> {
@logMethod
findByEmail(email: string): User | undefined {
for (const user of this.items.values()) {
if (user.email === email) {
this.logger.log(`Found user by email: ${email}`);
return user;
}
}
this.logger.log(`User with email: ${email} not found`);
return undefined;
}
@logMethod
findByAgeRange(minAge: number, maxAge: number): User[] {
const result: User[] = [];
for (const user of this.items.values()) {
if (user.age && user.age >= minAge && user.age <= maxAge) {
result.push(user);
}
}
this.logger.log(`Found ${result.length} users in age range ${minAge}-${maxAge}`);
return result;
}
}
// 使用示例
const logger = new ConsoleLogger();
const userRepo = new UserRepository(logger);
// 添加用户
userRepo.add({ id: "1", name: "John Doe", email: "john.doe@example.com", age: 30 });
userRepo.add({ id: "2", name: "Jane Smith", email: "jane.smith@example.com", age: 25 });
userRepo.add({ id: "3", name: "Bob Johnson", email: "bob.johnson@example.com", age: 35 });
// 获取所有用户
const allUsers = userRepo.getAll();
console.log("All users:", allUsers);
// 根据ID获取用户
const user = userRepo.get("2");
console.log("User with id 2:", user);
// 更新用户
userRepo.update("1", { age: 31 });
// 根据邮箱查找用户
const userByEmail = userRepo.findByEmail("jane.smith@example.com");
console.log("User by email:", userByEmail);
// 查找特定年龄范围内的用户
const usersByAgeRange = userRepo.findByAgeRange(25, 32);
console.log("Users in age range 25-32:", usersByAgeRange);
// 删除用户
userRepo.delete("3");
// 再次获取所有用户
const remainingUsers = userRepo.getAll();
console.log("Remaining users:", remainingUsers);我们可以使用AI代码解释器来帮助我们理解这段代码:
// 使用AI代码解释器理解上述代码
// 假设我们有一个AI助手函数,用于解释代码
function explainCode(code: string): string {
// 实际应用中,这里会调用AI API来解释代码
// 为了示例,我们直接返回一段解释
return `这段代码展示了TypeScript中的几个高级面向对象编程概念:
1. **接口与实现**:定义了Logger接口和它的实现类ConsoleLogger。
2. **装饰器**:使用了logMethod装饰器来记录方法的调用、参数和返回值。
3. **泛型类**:定义了一个抽象的泛型基类BaseRepository<T>,它接受一个类型参数T,并约束T必须有一个id属性。
4. **继承与多态**:UserRepository类继承自BaseRepository<User>,并重写或扩展了其父类的方法。
5. **抽象类**:BaseRepository是一个抽象类,不能直接实例化,只能被继承。
6. **访问修饰符**:使用了protected访问修饰符来限制属性和方法的访问范围。
7. **工具类型**:使用了Partial<T>工具类型来表示一个对象的部分属性。
代码的核心功能是实现了一个通用的仓库模式,用于管理具有id属性的对象,特别是用户对象。它提供了添加、获取、更新、删除和查询对象的功能,并使用日志记录所有操作。`;
}
// 调用解释函数
const explanation = explainCode(`// 上面的代码...`);
console.log(explanation);AI代码生成器可以根据我们的描述或需求,自动生成TypeScript代码。这对于快速实现简单的类、接口或函数非常有用。
示例:
// 使用AI代码生成器生成TypeScript代码
// 假设我们有一个AI助手函数,用于生成代码
function generateCode(prompt: string): string {
// 实际应用中,这里会调用AI API来生成代码
// 为了示例,我们直接返回一段预定义的代码
if (prompt.includes("生成一个简单的动物类层次结构")) {
return `// 动物类层次结构
// 基类
abstract class Animal {
protected name: string;
protected age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
// 抽象方法,子类必须实现
abstract makeSound(): void;
// 具体方法
eat(food: string): void {
console.log(`${this.name} is eating ${food}.`);
}
sleep(): void {
console.log(`${this.name} is sleeping.`);
}
getInfo(): string {
return `${this.name} is ${this.age} years old.`;
}
}
// 派生类 - 狗
class Dog extends Animal {
private breed: string;
constructor(name: string, age: number, breed: string) {
super(name, age);
this.breed = breed;
}
// 实现抽象方法
makeSound(): void {
console.log(`${this.name} barks: Woof! Woof!`);
}
// 特有方法
fetch(): void {
console.log(`${this.name} is fetching the ball.`);
}
// 覆盖父类方法
getInfo(): string {
return `${super.getInfo()} It's a ${this.breed}.`;
}
}
// 派生类 - 猫
class Cat extends Animal {
private color: string;
constructor(name: string, age: number, color: string) {
super(name, age);
this.color = color;
}
// 实现抽象方法
makeSound(): void {
console.log(`${this.name} meows: Meow! Meow!`);
}
// 特有方法
purr(): void {
console.log(`${this.name} is purring.`);
}
// 覆盖父类方法
getInfo(): string {
return `${super.getInfo()} It's a ${this.color} cat.`;
}
}
// 派生类 - 鸟
class Bird extends Animal {
private canFly: boolean;
constructor(name: string, age: number, canFly: boolean) {
super(name, age);
this.canFly = canFly;
}
// 实现抽象方法
makeSound(): void {
console.log(`${this.name} sings: Tweet! Tweet!`);
}
// 特有方法
fly(): void {
if (this.canFly) {
console.log(`${this.name} is flying.`);
} else {
console.log(`${this.name} can't fly.`);
}
}
// 覆盖父类方法
getInfo(): string {
return `${super.getInfo()} It ${this.canFly ? 'can' : 'can\'t'} fly.`;
}
}
// 使用示例
const animals: Animal[] = [
new Dog("Rex", 3, "German Shepherd"),
new Cat("Whiskers", 2, "Orange"),
new Bird("Tweety", 1, true)
];
// 多态:调用不同子类的方法
for (const animal of animals) {
console.log(animal.getInfo());
animal.makeSound();
animal.eat("generic food");
animal.sleep();
console.log("-------------------");
}
// 类型守卫和特有方法调用
for (const animal of animals) {
if (animal instanceof Dog) {
animal.fetch();
} else if (animal instanceof Cat) {
animal.purr();
} else if (animal instanceof Bird) {
animal.fly();
}
}`;
} else if (prompt.includes("生成一个简单的HTTP请求类")) {
return `// 简单的HTTP请求类
class HttpClient {
private baseUrl: string;
private timeout: number;
constructor(baseUrl: string, timeout: number = 5000) {
this.baseUrl = baseUrl;
this.timeout = timeout;
}
// 通用请求方法
private async request<T>(
method: 'GET' | 'POST' | 'PUT' | 'DELETE',
endpoint: string,
data?: any,
headers: Record<string, string> = {}
): Promise<T> {
const url = `${this.baseUrl}/${endpoint}`;
const options: RequestInit = {
method,
headers: {
'Content-Type': 'application/json',
...headers
},
timeout: this.timeout
};
if (data) {
options.body = JSON.stringify(data);
}
try {
const response = await fetch(url, options);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json() as T;
} catch (error) {
console.error(`Request failed: ${error instanceof Error ? error.message : String(error)}`);
throw error;
}
}
// GET请求
async get<T>(endpoint: string, headers: Record<string, string> = {}): Promise<T> {
return this.request<T>('GET', endpoint, undefined, headers);
}
// POST请求
async post<T>(endpoint: string, data?: any, headers: Record<string, string> = {}): Promise<T> {
return this.request<T>('POST', endpoint, data, headers);
}
// PUT请求
async put<T>(endpoint: string, data?: any, headers: Record<string, string> = {}): Promise<T> {
return this.request<T>('PUT', endpoint, data, headers);
}
// DELETE请求
async delete<T>(endpoint: string, headers: Record<string, string> = {}): Promise<T> {
return this.request<T>('DELETE', endpoint, undefined, headers);
}
// 设置基础URL
setBaseUrl(baseUrl: string): void {
this.baseUrl = baseUrl;
}
// 设置超时时间
setTimeout(timeout: number): void {
this.timeout = timeout;
}
}
// 使用示例
// 定义API响应类型
interface User {
id: number;
name: string;
email: string;
}
interface ApiResponse<T> {
success: boolean;
data: T;
message?: string;
}
// 创建HTTP客户端实例
const apiClient = new HttpClient('https://api.example.com', 10000);
// 使用HTTP客户端进行API调用
async function exampleUsage() {
try {
// GET请求:获取所有用户
const users = await apiClient.get<ApiResponse<User[]>>('users');
console.log('Users:', users.data);
// POST请求:创建新用户
const newUser = await apiClient.post<ApiResponse<User>>('users', {
name: 'John Doe',
email: 'john.doe@example.com'
});
console.log('Created user:', newUser.data);
// PUT请求:更新用户
const updatedUser = await apiClient.put<ApiResponse<User>>(`users/${newUser.data.id}`, {
name: 'Jane Doe'
});
console.log('Updated user:', updatedUser.data);
// DELETE请求:删除用户
const deleteResult = await apiClient.delete<ApiResponse<null>>(`users/${newUser.data.id}`);
console.log('Delete result:', deleteResult.success);
} catch (error) {
console.error('API call failed:', error);
}
}
// 运行示例
// exampleUsage();`;
}
return `// 无法生成匹配的代码。请提供更具体的需求。`;
}
// 调用代码生成函数
const animalCode = generateCode("生成一个简单的动物类层次结构");
console.log("生成的动物类层次结构代码:");
console.log(animalCode);
const httpClientCode = generateCode("生成一个简单的HTTP请求类");
console.log("\n生成的HTTP请求类代码:");
console.log(httpClientCode);AI代码优化器可以帮助我们改进现有的TypeScript代码,使其更加高效、可读性更强或更符合最佳实践。
示例:
// 使用AI代码优化器改进TypeScript代码
// 假设我们有一个AI助手函数,用于优化代码
function optimizeCode(code: string): string {
// 实际应用中,这里会调用AI API来优化代码
// 为了示例,我们直接返回一段优化后的代码
if (code.includes("// 原始代码:一个简单的用户管理类")) {
return `// 优化后的代码:用户管理类
class UserManager {
// 使用private readonly修饰符保证不可变性
private readonly users: Map<string, User> = new Map();
// 使用类型别名提高可读性
constructor(private readonly logger: Logger = console) {}
// 添加用户 - 使用nullish coalescing operator处理可选参数
addUser(id: string, name: string, email: string, age?: number): void {
if (this.users.has(id)) {
this.logger.warn(`User with ID ${id} already exists.`);
return;
}
const user: User = { id, name, email, age: age ?? undefined };
this.users.set(id, user);
this.logger.log(`Added user: ${name}`);
}
// 获取用户 - 使用optional chaining和nullish coalescing提高健壮性
getUser(id: string): User | undefined {
const user = this.users.get(id);
if (!user) {
this.logger.warn(`User with ID ${id} not found.`);
}
return user;
}
// 获取所有用户 - 使用数组展开运算符简化代码
getAllUsers(): User[] {
return [...this.users.values()];
}
// 更新用户 - 使用partial类型和对象展开运算符简化更新逻辑
updateUser(id: string, updates: Partial<User>): boolean {
const user = this.getUser(id);
if (!user) {
return false;
}
// 创建更新后的用户对象,保留未更新的属性
const updatedUser = { ...user, ...updates };
this.users.set(id, updatedUser);
this.logger.log(`Updated user: ${id}`);
return true;
}
// 删除用户 - 使用Map的delete方法直接返回结果
deleteUser(id: string): boolean {
const result = this.users.delete(id);
if (result) {
this.logger.log(`Deleted user: ${id}`);
} else {
this.logger.warn(`Failed to delete: User with ID ${id} not found.`);
}
return result;
}
// 搜索用户 - 使用数组方法和箭头函数简化搜索逻辑
searchUsers(predicate: (user: User) => boolean): User[] {
return this.getAllUsers().filter(predicate);
}
// 获取用户数量 - 使用getter简化访问
get userCount(): number {
return this.users.size;
}
// 清除所有用户
clearAllUsers(): void {
this.users.clear();
this.logger.log(`Cleared all ${this.userCount} users.`);
}
}
// 定义用户接口
interface User {
id: string;
name: string;
email: string;
age?: number;
}
// 定义日志接口
interface Logger {
log(message: string): void;
warn(message: string): void;
error(message: string): void;
}
// 默认的控制台日志实现
const consoleLogger: Logger = {
log: console.log,
warn: console.warn,
error: console.error
};
// 使用示例
const userManager = new UserManager();
// 添加用户
userManager.addUser("1", "John Doe", "john.doe@example.com", 30);
userManager.addUser("2", "Jane Smith", "jane.smith@example.com");
userManager.addUser("3", "Bob Johnson", "bob.johnson@example.com", 35);
// 获取用户数量
console.log(`Total users: ${userManager.userCount}`);
// 获取所有用户
const allUsers = userManager.getAllUsers();
console.log("All users:", allUsers);
// 更新用户
userManager.updateUser("1", { age: 31 });
// 搜索用户
const usersWithAge = userManager.searchUsers(user => user.age !== undefined);
console.log("Users with age specified:", usersWithAge);
// 删除用户
userManager.deleteUser("2");
// 再次获取用户数量
console.log(`Remaining users: ${userManager.userCount}`);
// 清除所有用户
// userManager.clearAllUsers();`;
}
return `// 无法优化匹配的代码。请提供具体的代码片段。`;
}
// 原始代码
const originalCode = `// 原始代码:一个简单的用户管理类
class UserManager {
users: any = {};
constructor() {
this.users = {};
}
addUser(id, name, email, age) {
if (this.users[id]) {
console.log('User with ID ' + id + ' already exists.');
return;
}
this.users[id] = {id: id, name: name, email: email};
if (age) {
this.users[id].age = age;
}
console.log('Added user: ' + name);
}
getUser(id) {
if (!this.users[id]) {
console.log('User with ID ' + id + ' not found.');
return null;
}
return this.users[id];
}
getAllUsers() {
let result = [];
for (let id in this.users) {
result.push(this.users[id]);
}
return result;
}
updateUser(id, updates) {
let user = this.getUser(id);
if (!user) {
return false;
}
for (let key in updates) {
user[key] = updates[key];
}
console.log('Updated user: ' + id);
return true;
}
deleteUser(id) {
if (!this.users[id]) {
console.log('Failed to delete: User with ID ' + id + ' not found.');
return false;
}
delete this.users[id];
console.log('Deleted user: ' + id);
return true;
}
getCount() {
let count = 0;
for (let id in this.users) {
count++;
}
return count;
}
}`;
// 调用优化函数
const optimizedCode = optimizeCode(originalCode);
console.log("原始代码:");
console.log(originalCode);
console.log("\n优化后的代码:");
console.log(optimizedCode);AI错误检测器可以帮助我们发现并修复TypeScript代码中的错误和潜在问题。
示例:
// 使用AI错误检测器查找并修复TypeScript代码中的问题
// 假设我们有一个AI助手函数,用于检测错误
function detectErrors(code: string): { errors: string[], suggestions: string[] } {
// 实际应用中,这里会调用AI API来检测错误
// 为了示例,我们直接返回预定义的错误和建议
if (code.includes("// 有错误的代码")) {
return {
errors: [
"1. 类属性'name'没有初始化",
"2. 方法'greet'中的参数'time'类型声明错误,应该是string而不是number",
"3. 方法'calculateAge'中使用了未定义的变量'currentYear'",
"4. 缺少必要的访问修饰符,可能导致封装性问题",
"5. 'Person'类没有实现'Employee'接口中必需的'position'属性和'work'方法"
],
suggestions: [
"1. 在构造函数中初始化'name'属性或提供默认值",
"2. 将'time'参数类型改为string,或修改函数实现以接受number类型",
"3. 添加'currentYear'变量的定义,或使用new Date().getFullYear()",
"4. 为所有类属性添加private、protected或public访问修饰符",
"5. 在'Person'类中实现'position'属性和'work'方法,或移除'implements Employee'声明"
]
};
}
return { errors: [], suggestions: [] };
}
// 有错误的代码
const buggyCode = `// 有错误的代码
interface Employee {
id: number;
name: string;
position: string;
work(): void;
}
class Person implements Employee {
id: number;
name: string;
age: number;
constructor(id: number, age: number) {
this.id = id;
this.age = age;
}
greet(time: number): void {
console.log(`Hello, my name is ${this.name}. Good ${time}!`);
}
calculateAge(): number {
return currentYear - this.age;
}
}`;
// 调用错误检测函数
const result = detectErrors(buggyCode);
console.log("检测到的错误:");
result.errors.forEach((error, index) => {
console.log(`${index + 1}. ${error}`);
});
console.log("\n建议:");
result.suggestions.forEach((suggestion, index) => {
console.log(`${index + 1}. ${suggestion}`);
});
// 修复错误后的代码
const fixedCode = `// 修复后的代码
interface Employee {
id: number;
name: string;
position: string;
work(): void;
}
class Person implements Employee {
private id: number;
private name: string;
private age: number;
private position: string;
constructor(id: number, name: string, age: number, position: string = "Employee") {
this.id = id;
this.name = name;
this.age = age;
this.position = position;
}
greet(time: string): void {
console.log(`Hello, my name is ${this.name}. Good ${time}!`);
}
calculateAge(): number {
const currentYear = new Date().getFullYear();
return currentYear - this.age;
}
work(): void {
console.log(`${this.name} (${this.position}) is working.`);
}
// 添加getter方法以访问私有属性
getId(): number {
return this.id;
}
getName(): string {
return this.name;
}
getAge(): number {
return this.age;
}
getPosition(): string {
return this.position;
}
// 添加setter方法以修改私有属性
setPosition(position: string): void {
this.position = position;
}
}`;
console.log("\n修复后的代码:");
console.log(fixedCode);
// 使用修复后的代码
const person = new Person(1, "John Doe", 30, "Developer");
console.log(`ID: ${person.getId()}`);
console.log(`Name: ${person.getName()}`);
console.log(`Age: ${person.getAge()}`);
console.log(`Position: ${person.getPosition()}`);
console.log(`Birth year: ${person.calculateAge()}`);
person.greet("morning");
person.work();
person.setPosition("Senior Developer");
console.log(`New position: ${person.getPosition()}`);
person.work();AI学习助手可以回答我们关于TypeScript面向对象编程的问题,并提供个性化的学习建议。
示例:
// 使用AI学习助手获取TypeScript面向对象编程的学习建议
// 假设我们有一个AI助手函数,用于回答问题和提供建议
function askAIAssistant(question: string): string {
// 实际应用中,这里会调用AI API来回答问题
// 为了示例,我们直接返回预定义的答案
if (question.includes("如何学习TypeScript面向对象编程")) {
return `学习TypeScript面向对象编程的建议:
1. **掌握基础知识**:
- 先学习JavaScript的基本概念,包括函数、对象、原型链等
- 理解TypeScript的类型系统,包括基本类型、联合类型、交叉类型等
- 学习ES6+的新特性,如箭头函数、解构赋值、模板字符串等
2. **学习面向对象编程基础**:
- 理解类、对象、继承、多态、封装等核心概念
- 学习如何定义和使用接口
- 掌握访问修饰符(public、private、protected)的使用
3. **实践TypeScript的高级特性**:
- 学习泛型编程,包括泛型类、泛型接口、泛型函数
- 掌握类型守卫和类型断言
- 学习装饰器的使用
- 理解抽象类和具体类的区别
4. **构建实际项目**:
- 从小型项目开始,如待办事项应用、计算器等
- 逐渐增加项目复杂度,如构建一个简单的API客户端、表单验证库等
- 尝试重构现有项目,应用所学的面向对象编程原则
5. **参考优质资源**:
- TypeScript官方文档:https://www.typescriptlang.org/docs/
- 优质教程和书籍,如《TypeScript Deep Dive》
- GitHub上的开源项目,学习其他人的代码风格和最佳实践
6. **使用AI辅助工具**:
- 利用AI代码解释器理解复杂代码
- 使用AI代码生成器快速实现简单功能
- 通过AI错误检测器查找并修复代码中的问题
- 向AI学习助手提问,获取个性化的学习建议
7. **持续练习和反思**:
- 每天坚持编写TypeScript代码
- 参与代码审查,学习他人的反馈
- 定期回顾和重构自己的代码,应用新学到的知识
- 尝试解决TypeScript相关的编程挑战和问题
8. **加入社区**:
- 参与TypeScript相关的讨论和活动
- 在社区中分享自己的学习经验和项目
- 向其他开发者学习,互相帮助和成长`;
} else if (question.includes("TypeScript面向对象编程的最佳实践")) {
return `TypeScript面向对象编程的最佳实践:
1. **优先使用接口定义类型**:
- 使用接口定义对象的形状和行为
- 接口可以被多个类实现,提高代码的可扩展性
2. **合理使用访问修饰符**:
- 默认为public,但最好显式声明
- 使用private保护内部状态
- 使用protected允许子类访问
- 为需要暴露的属性提供getter和setter
3. **优先使用类型安全的代码**:
- 避免使用any类型
- 使用unknown类型代替any类型
- 利用类型守卫处理联合类型
4. **合理使用泛型**:
- 使用泛型提高代码的复用性
- 为泛型添加适当的约束
- 利用TypeScript内置的泛型工具类型
5. **设计良好的类层次结构**:
- 遵循单一职责原则,一个类只做一件事
- 避免过深的继承层次,考虑使用组合代替继承
- 合理使用抽象类定义共同行为
6. **使用装饰器增强类的功能**:
- 使用装饰器实现横切关注点
- 但要注意装饰器仍处于实验阶段
7. **编写清晰的文档**:
- 为类、方法和属性添加JSDoc注释
- 说明参数、返回值和可能抛出的异常
8. **使用类型别名和字面量类型**:
- 为复杂的类型创建有意义的别名
- 使用字面量类型限制取值范围
9. **优化导入和导出**:
- 使用命名导出而不是默认导出
- 考虑使用barrel文件简化导入
10. **利用TypeScript的高级类型特性**:
- 使用映射类型转换现有类型
- 使用条件类型实现类型的条件分支
- 使用索引类型访问对象的属性类型
11. **编写可测试的代码**:
- 依赖注入,避免硬编码依赖
- 模拟对象和接口,便于单元测试
12. **保持代码简洁**:
- 避免过度设计和过早优化
- 优先使用函数式编程的思想处理数据转换`;
}
return `// 无法回答此问题。请尝试提供更具体的问题。`;
}
// 向AI助手提问
const question1 = "如何学习TypeScript面向对象编程?";
const answer1 = askAIAssistant(question1);
console.log(`问题1:${question1}`);
console.log(`答案1:${answer1}`);
const question2 = "TypeScript面向对象编程的最佳实践有哪些?";
const answer2 = askAIAssistant(question2);
console.log(`\n问题2:${question2}`);
console.log(`答案2:${answer2}`);
const question3 = "什么是泛型约束,在什么情况下应该使用它?";
const answer3 = askAIAssistant(question3);
console.log(`\n问题3:${question3}`);
console.log(`答案3:${answer3}`);现在,让我们将所学的TypeScript面向对象编程知识应用到实际项目中。我们将构建一个简单的电子商务系统,包括产品管理、购物车、订单处理等功能。
这个电子商务系统将包含以下核心功能:
我们将使用TypeScript的面向对象编程特性来实现这些功能,包括类、接口、继承、多态、泛型等。
首先,我们来设计核心的数据模型:
// 定义基本的数据类型
export interface Product {
id: string;
name: string;
description: string;
price: number;
category: string;
stock: number;
images: string[];
}
export interface User {
id: string;
username: string;
email: string;
password: string; // 实际应用中应加密存储
fullName: string;
address: string;
phone: string;
isAdmin: boolean;
createdAt: Date;
updatedAt: Date;
}
export interface CartItem {
productId: string;
quantity: number;
priceAtPurchase: number;
}
export interface ShoppingCart {
id: string;
userId: string;
items: CartItem[];
createdAt: Date;
updatedAt: Date;
}
export interface Order {
id: string;
userId: string;
items: CartItem[];
totalAmount: number;
status: 'pending' | 'processing' | 'shipped' | 'delivered' | 'cancelled';
shippingAddress: string;
paymentMethod: string;
paymentStatus: 'pending' | 'paid' | 'failed';
createdAt: Date;
updatedAt: Date;
}
export interface Payment {
id: string;
orderId: string;
amount: number;
method: string;
status: 'pending' | 'completed' | 'failed' | 'refunded';
transactionId: string;
createdAt: Date;
}
// 库存管理接口
interface Inventory {
checkStock(productId: string, quantity: number): boolean;
updateStock(productId: string, quantity: number): boolean;
getStock(productId: string): number;
}
// 通知服务接口
interface NotificationService {
sendOrderConfirmation(orderId: string, userId: string): void;
sendPaymentConfirmation(paymentId: string, userId: string): void;
sendShippingNotification(orderId: string, userId: string): void;
}接下来,我们来实现核心的服务类:
// 产品服务类
class ProductService {
private products: Map<string, Product> = new Map();
private inventory: Inventory;
constructor(inventory: Inventory) {
this.inventory = inventory;
}
addProduct(product: Omit<Product, 'id'>): Product {
const id = `prod_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
const newProduct: Product = {
...product,
id
};
this.products.set(id, newProduct);
return newProduct;
}
getProduct(id: string): Product | undefined {
return this.products.get(id);
}
getAllProducts(): Product[] {
return Array.from(this.products.values());
}
getProductsByCategory(category: string): Product[] {
return Array.from(this.products.values()).filter(product => product.category === category);
}
updateProduct(id: string, updates: Partial<Product>): Product | null {
const product = this.products.get(id);
if (!product) {
return null;
}
const updatedProduct: Product = {
...product,
...updates,
updatedAt: new Date()
};
this.products.set(id, updatedProduct);
return updatedProduct;
}
deleteProduct(id: string): boolean {
return this.products.delete(id);
}
// 搜索产品
searchProducts(query: string): Product[] {
const lowercaseQuery = query.toLowerCase();
return Array.from(this.products.values()).filter(product =>
product.name.toLowerCase().includes(lowercaseQuery) ||
product.description.toLowerCase().includes(lowercaseQuery) ||
product.category.toLowerCase().includes(lowercaseQuery)
);
}
// 检查产品是否有库存
hasStock(productId: string, quantity: number): boolean {
return this.inventory.checkStock(productId, quantity);
}
}
// 库存服务实现
class InventoryService implements Inventory {
private stockLevels: Map<string, number> = new Map();
checkStock(productId: string, quantity: number): boolean {
const currentStock = this.stockLevels.get(productId) || 0;
return currentStock >= quantity;
}
updateStock(productId: string, quantity: number): boolean {
const currentStock = this.stockLevels.get(productId) || 0;
const newStock = currentStock + quantity;
if (newStock < 0) {
return false; // 库存不足
}
this.stockLevels.set(productId, newStock);
return true;
}
getStock(productId: string): number {
return this.stockLevels.get(productId) || 0;
}
// 初始化产品库存
setStock(productId: string, quantity: number): void {
if (quantity >= 0) {
this.stockLevels.set(productId, quantity);
}
}
}
// 购物车服务类
class CartService {
private carts: Map<string, ShoppingCart> = new Map();
private productService: ProductService;
constructor(productService: ProductService) {
this.productService = productService;
}
// 获取或创建购物车
getOrCreateCart(userId: string): ShoppingCart {
let cart = this.carts.get(userId);
if (!cart) {
cart = {
id: `cart_${userId}`,
userId,
items: [],
createdAt: new Date(),
updatedAt: new Date()
};
this.carts.set(userId, cart);
}
return cart;
}
// 添加商品到购物车
addToCart(userId: string, productId: string, quantity: number = 1): boolean {
const product = this.productService.getProduct(productId);
if (!product || !this.productService.hasStock(productId, quantity)) {
return false;
}
const cart = this.getOrCreateCart(userId);
const existingItemIndex = cart.items.findIndex(item => item.productId === productId);
if (existingItemIndex >= 0) {
// 更新现有商品数量
cart.items[existingItemIndex].quantity += quantity;
} else {
// 添加新商品
cart.items.push({
productId,
quantity,
priceAtPurchase: product.price
});
}
cart.updatedAt = new Date();
this.carts.set(userId, cart);
return true;
}
// 更新购物车中商品数量
updateCartItem(userId: string, productId: string, quantity: number): boolean {
if (quantity <= 0) {
return this.removeFromCart(userId, productId);
}
const cart = this.carts.get(userId);
if (!cart) {
return false;
}
const itemIndex = cart.items.findIndex(item => item.productId === productId);
if (itemIndex === -1) {
return false;
}
const product = this.productService.getProduct(productId);
if (!product || !this.productService.hasStock(productId, quantity - cart.items[itemIndex].quantity)) {
return false;
}
cart.items[itemIndex].quantity = quantity;
cart.updatedAt = new Date();
this.carts.set(userId, cart);
return true;
}
// 从购物车移除商品
removeFromCart(userId: string, productId: string): boolean {
const cart = this.carts.get(userId);
if (!cart) {
return false;
}
const initialLength = cart.items.length;
cart.items = cart.items.filter(item => item.productId !== productId);
if (cart.items.length !== initialLength) {
cart.updatedAt = new Date();
this.carts.set(userId, cart);
return true;
}
return false;
}
// 清空购物车
clearCart(userId: string): boolean {
const cart = this.carts.get(userId);
if (!cart || cart.items.length === 0) {
return false;
}
cart.items = [];
cart.updatedAt = new Date();
this.carts.set(userId, cart);
return true;
}
// 计算购物车总价
calculateCartTotal(userId: string): number {
const cart = this.carts.get(userId);
if (!cart) {
return 0;
}
return cart.items.reduce((total, item) => {
const product = this.productService.getProduct(item.productId);
// 使用当前产品价格或添加时的价格
const price = product ? product.price : item.priceAtPurchase;
return total + (price * item.quantity);
}, 0);
}
// 获取购物车中的商品详情
getCartItemsWithDetails(userId: string): { product: Product, quantity: number, subtotal: number }[] {
const cart = this.carts.get(userId);
if (!cart) {
return [];
}
return cart.items.map(item => {
const product = this.productService.getProduct(item.productId);
if (!product) {
// 产品可能已被删除,但仍在购物车中
return {
product: {
id: item.productId,
name: "[已删除产品]",
description: "此产品已从系统中删除",
price: item.priceAtPurchase,
category: "",
stock: 0,
images: []
},
quantity: item.quantity,
subtotal: item.priceAtPurchase * item.quantity
};
}
return {
product,
quantity: item.quantity,
subtotal: product.price * item.quantity
};
});
}
}
// 用户服务类
class UserService {
private users: Map<string, User> = new Map();
private currentUser: User | null = null;
// 注册用户
register(userData: Omit<User, 'id' | 'createdAt' | 'updatedAt' | 'isAdmin'>): User | null {
// 检查用户名或邮箱是否已存在
for (const user of this.users.values()) {
if (user.username === userData.username || user.email === userData.email) {
return null;
}
}
const id = `user_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
const newUser: User = {
...userData,
id,
isAdmin: false, // 默认不是管理员
createdAt: new Date(),
updatedAt: new Date()
};
this.users.set(id, newUser);
return newUser;
}
// 用户登录
login(username: string, password: string): User | null {
for (const user of this.users.values()) {
if (user.username === username && user.password === password) {
this.currentUser = user;
return user;
}
}
return null;
}
// 用户登出
logout(): void {
this.currentUser = null;
}
// 获取当前登录用户
getCurrentUser(): User | null {
return this.currentUser;
}
// 获取用户信息
getUserById(id: string): User | undefined {
return this.users.get(id);
}
// 更新用户信息
updateUser(id: string, updates: Partial<Omit<User, 'id' | 'createdAt' | 'isAdmin'>>): User | null {
const user = this.users.get(id);
if (!user) {
return null;
}
// 检查新用户名或邮箱是否已被使用
if (updates.username || updates.email) {
for (const otherUser of this.users.values()) {
if (otherUser.id !== id &&
((updates.username && otherUser.username === updates.username) ||
(updates.email && otherUser.email === updates.email))) {
return null;
}
}
}
const updatedUser: User = {
...user,
...updates,
updatedAt: new Date()
};
this.users.set(id, updatedUser);
// 如果更新的是当前登录用户,也要更新currentUser
if (this.currentUser && this.currentUser.id === id) {
this.currentUser = updatedUser;
}
return updatedUser;
}
// 删除用户
deleteUser(id: string): boolean {
// 不能删除当前登录用户或管理员
const user = this.users.get(id);
if (!user || (this.currentUser && this.currentUser.id === id) || user.isAdmin) {
return false;
}
return this.users.delete(id);
}
// 检查用户是否是管理员
isAdmin(userId: string): boolean {
const user = this.users.get(userId);
return user ? user.isAdmin : false;
}
}
// 订单服务类
class OrderService {
private orders: Map<string, Order> = new Map();
private cartService: CartService;
private inventory: Inventory;
private notificationService: NotificationService;
private paymentService: PaymentService;
constructor(
cartService: CartService,
inventory: Inventory,
notificationService: NotificationService,
paymentService: PaymentService
) {
this.cartService = cartService;
this.inventory = inventory;
this.notificationService = notificationService;
this.paymentService = paymentService;
}
// 创建订单
createOrder(userId: string, shippingAddress: string, paymentMethod: string): Order | null {
const cartItems = this.cartService.getCartItemsWithDetails(userId);
if (cartItems.length === 0) {
return null;
}
// 检查库存
for (const item of cartItems) {
if (!this.inventory.checkStock(item.product.id, item.quantity)) {
return null;
}
}
// 计算总价
const totalAmount = this.cartService.calculateCartTotal(userId);
// 创建订单
const orderId = `order_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
const order: Order = {
id: orderId,
userId,
items: cartItems.map(item => ({
productId: item.product.id,
quantity: item.quantity,
priceAtPurchase: item.product.price
})),
totalAmount,
status: 'pending',
shippingAddress,
paymentMethod,
paymentStatus: 'pending',
createdAt: new Date(),
updatedAt: new Date()
};
this.orders.set(orderId, order);
// 更新库存
for (const item of cartItems) {
this.inventory.updateStock(item.product.id, -item.quantity);
}
// 清空购物车
this.cartService.clearCart(userId);
// 发送订单确认通知
this.notificationService.sendOrderConfirmation(orderId, userId);
// 处理支付
if (paymentMethod === 'online') {
this.processPayment(orderId);
}
return order;
}
// 处理支付
processPayment(orderId: string): boolean {
const order = this.orders.get(orderId);
if (!order || order.paymentStatus !== 'pending') {
return false;
}
// 调用支付服务处理支付
const paymentSuccess = this.paymentService.processPayment(orderId, order.totalAmount, order.paymentMethod);
if (paymentSuccess) {
order.paymentStatus = 'paid';
order.status = 'processing';
order.updatedAt = new Date();
this.orders.set(orderId, order);
// 发送支付确认通知
this.notificationService.sendPaymentConfirmation(orderId, order.userId);
return true;
}
order.paymentStatus = 'failed';
order.updatedAt = new Date();
this.orders.set(orderId, order);
return false;
}
// 获取订单
getOrder(id: string): Order | undefined {
return this.orders.get(id);
}
// 获取用户的所有订单
getUserOrders(userId: string): Order[] {
return Array.from(this.orders.values()).filter(order => order.userId === userId);
}
// 更新订单状态
updateOrderStatus(orderId: string, status: Order['status']): boolean {
const order = this.orders.get(orderId);
if (!order) {
return false;
}
order.status = status;
order.updatedAt = new Date();
this.orders.set(orderId, order);
// 如果订单已发货,发送发货通知
if (status === 'shipped') {
this.notificationService.sendShippingNotification(orderId, order.userId);
}
return true;
}
// 取消订单
cancelOrder(orderId: string): boolean {
const order = this.orders.get(orderId);
if (!order || order.status === 'delivered' || order.status === 'shipped') {
return false; // 已发货或已送达的订单不能取消
}
// 恢复库存
if (order.paymentStatus === 'paid') {
// 这里应该处理退款逻辑
// 简化示例中省略
}
order.status = 'cancelled';
order.updatedAt = new Date();
this.orders.set(orderId, order);
return true;
}
}
// 支付服务类
class PaymentService {
private payments: Map<string, Payment> = new Map();
// 处理支付
processPayment(orderId: string, amount: number, method: string): boolean {
// 模拟支付过程
// 在实际应用中,这里应该调用第三方支付API
const isSuccess = Math.random() > 0.1; // 90%的成功率
const paymentId = `payment_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
const transactionId = `txn_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
const payment: Payment = {
id: paymentId,
orderId,
amount,
method,
status: isSuccess ? 'completed' : 'failed',
transactionId,
createdAt: new Date()
};
this.payments.set(paymentId, payment);
return isSuccess;
}
// 获取支付信息
getPayment(id: string): Payment | undefined {
return this.payments.get(id);
}
// 获取订单的支付记录
getPaymentsByOrderId(orderId: string): Payment[] {
return Array.from(this.payments.values()).filter(payment => payment.orderId === orderId);
}
// 处理退款
refundPayment(paymentId: string): boolean {
const payment = this.payments.get(paymentId);
if (!payment || payment.status !== 'completed') {
return false; // 只有已完成的支付才能退款
}
// 模拟退款过程
const isSuccess = Math.random() > 0.1; // 90%的成功率
if (isSuccess) {
payment.status = 'refunded';
this.payments.set(paymentId, payment);
}
return isSuccess;
}
}
// 通知服务实现
class EmailNotificationService implements NotificationService {
// 发送订单确认邮件
sendOrderConfirmation(orderId: string, userId: string): void {
console.log(`[邮件通知] 订单确认:向用户 ${userId} 发送订单 ${orderId} 的确认邮件`);
// 在实际应用中,这里应该调用邮件发送API
}
// 发送支付确认邮件
sendPaymentConfirmation(paymentId: string, userId: string): void {
console.log(`[邮件通知] 支付确认:向用户 ${userId} 发送支付 ${paymentId} 的确认邮件`);
// 在实际应用中,这里应该调用邮件发送API
}
// 发送发货通知邮件
sendShippingNotification(orderId: string, userId: string): void {
console.log(`[邮件通知] 发货通知:向用户 ${userId} 发送订单 ${orderId} 的发货通知邮件`);
// 在实际应用中,这里应该调用邮件发送API
}
}
// 模拟短信通知服务
class SMSNotificationService implements NotificationService {
// 发送订单确认短信
sendOrderConfirmation(orderId: string, userId: string): void {
console.log(`[短信通知] 订单确认:向用户 ${userId} 发送订单 ${orderId} 的确认短信`);
// 在实际应用中,这里应该调用短信发送API
}
// 发送支付确认短信
sendPaymentConfirmation(paymentId: string, userId: string): void {
console.log(`[短信通知] 支付确认:向用户 ${userId} 发送支付 ${paymentId} 的确认短信`);
// 在实际应用中,这里应该调用短信发送API
}
// 发送发货通知短信
sendShippingNotification(orderId: string, userId: string): void {
console.log(`[短信通知] 发货通知:向用户 ${userId} 发送订单 ${orderId} 的发货通知短信`);
// 在实际应用中,这里应该调用短信发送API
}
}
// 复合通知服务 - 同时发送多种通知
class CompositeNotificationService implements NotificationService {
private services: NotificationService[] = [];
constructor(...services: NotificationService[]) {
this.services = services;
}
// 添加通知服务
addService(service: NotificationService): void {
this.services.push(service);
}
// 发送订单确认通知
sendOrderConfirmation(orderId: string, userId: string): void {
for (const service of this.services) {
service.sendOrderConfirmation(orderId, userId);
}
}
// 发送支付确认通知
sendPaymentConfirmation(paymentId: string, userId: string): void {
for (const service of this.services) {
service.sendPaymentConfirmation(paymentId, userId);
}
}
// 发送发货通知
sendShippingNotification(orderId: string, userId: string): void {
for (const service of this.services) {
service.sendShippingNotification(orderId, userId);
}
}
}现在,让我们将这些服务集成在一起,并编写一个简单的使用示例:
// 初始化服务
const inventoryService = new InventoryService();
const emailService = new EmailNotificationService();
const smsService = new SMSNotificationService();
const notificationService = new CompositeNotificationService(emailService, smsService);
const paymentService = new PaymentService();
const productService = new ProductService(inventoryService);
const cartService = new CartService(productService);
const userService = new UserService();
const orderService = new OrderService(cartService, inventoryService, notificationService, paymentService);
// 创建电子商务系统类,作为外观模式的实现
class ECommerceSystem {
private productService: ProductService;
private cartService: CartService;
private userService: UserService;
private orderService: OrderService;
private inventoryService: InventoryService;
constructor(
productService: ProductService,
cartService: CartService,
userService: UserService,
orderService: OrderService,
inventoryService: InventoryService
) {
this.productService = productService;
this.cartService = cartService;
this.userService = userService;
this.orderService = orderService;
this.inventoryService = inventoryService;
}
// 用户相关方法
registerUser(userData: Omit<User, 'id' | 'createdAt' | 'updatedAt' | 'isAdmin'>) {
return this.userService.register(userData);
}
login(username: string, password: string) {
return this.userService.login(username, password);
}
logout() {
this.userService.logout();
}
getCurrentUser() {
return this.userService.getCurrentUser();
}
// 产品相关方法
addProduct(product: Omit<Product, 'id'>) {
const newProduct = this.productService.addProduct(product);
// 设置初始库存
this.inventoryService.setStock(newProduct.id, 100); // 默认每个产品有100个库存
return newProduct;
}
getProduct(id: string) {
return this.productService.getProduct(id);
}
getAllProducts() {
return this.productService.getAllProducts();
}
// 购物车相关方法
addToCart(userId: string, productId: string, quantity: number = 1) {
return this.cartService.addToCart(userId, productId, quantity);
}
viewCart(userId: string) {
return this.cartService.getCartItemsWithDetails(userId);
}
updateCartItem(userId: string, productId: string, quantity: number) {
return this.cartService.updateCartItem(userId, productId, quantity);
}
removeFromCart(userId: string, productId: string) {
return this.cartService.removeFromCart(userId, productId);
}
calculateCartTotal(userId: string) {
return this.cartService.calculateCartTotal(userId);
}
// 订单相关方法
createOrder(userId: string, shippingAddress: string, paymentMethod: string) {
return this.orderService.createOrder(userId, shippingAddress, paymentMethod);
}
getOrder(orderId: string) {
return this.orderService.getOrder(orderId);
}
getUserOrders(userId: string) {
return this.orderService.getUserOrders(userId);
}
updateOrderStatus(orderId: string, status: Order['status']) {
return this.orderService.updateOrderStatus(orderId, status);
}
}
// 创建电子商务系统实例
const ecommerce = new ECommerceSystem(
productService,
cartService,
userService,
orderService,
inventoryService
);
// 使用示例:模拟一个用户购物流程
function runDemo() {
console.log("====== 电子商务系统演示 ======");
// 1. 注册用户
console.log("\n1. 注册用户...");
const user = ecommerce.registerUser({
username: "johndoe",
email: "john.doe@example.com",
password: "password123", // 实际应用中应该加密存储
fullName: "John Doe",
address: "123 Main St, City",
phone: "123-456-7890"
});
if (!user) {
console.log("用户注册失败!");
return;
}
console.log(`用户注册成功:${user.username} (ID: ${user.id})`);
// 2. 添加一些产品
console.log("\n2. 添加产品...");
const product1 = ecommerce.addProduct({
name: "无线蓝牙耳机",
description: "高品质无线蓝牙耳机,降噪功能,长效续航",
price: 299.99,
category: "电子产品",
stock: 100, // 这个值会被InventoryService覆盖
images: ["https://example.com/images/headphones1.jpg"]
});
const product2 = ecommerce.addProduct({
name: "智能手表",
description: "多功能智能手表,健康监测,运动追踪",
price: 199.99,
category: "电子产品",
stock: 100, // 这个值会被InventoryService覆盖
images: ["https://example.com/images/watch1.jpg"]
});
const product3 = ecommerce.addProduct({
name: "机械键盘",
description: "青轴机械键盘,RGB背光,全键无冲",
price: 89.99,
category: "电脑配件",
stock: 100, // 这个值会被InventoryService覆盖
images: ["https://example.com/images/keyboard1.jpg"]
});
console.log(`添加产品成功:${product1.name}, ${product2.name}, ${product3.name}`);
// 3. 用户登录
console.log("\n3. 用户登录...");
const loggedInUser = ecommerce.login("johndoe", "password123");
if (!loggedInUser) {
console.log("登录失败!");
return;
}
console.log(`用户登录成功:${loggedInUser.username}`);
// 4. 添加商品到购物车
console.log("\n4. 添加商品到购物车...");
ecommerce.addToCart(user.id, product1.id, 1);
ecommerce.addToCart(user.id, product3.id, 2);
console.log("商品已添加到购物车");
// 5. 查看购物车
console.log("\n5. 查看购物车...");
const cartItems = ecommerce.viewCart(user.id);
console.log("购物车商品:");
cartItems.forEach(item => {
console.log(`- ${item.product.name} x ${item.quantity}: $${item.subtotal.toFixed(2)}`);
});
const cartTotal = ecommerce.calculateCartTotal(user.id);
console.log(`购物车总价:$${cartTotal.toFixed(2)}`);
// 6. 创建订单
console.log("\n6. 创建订单...");
const order = ecommerce.createOrder(user.id, "123 Main St, City", "online");
if (!order) {
console.log("创建订单失败!");
return;
}
console.log(`订单创建成功:${order.id}`);
console.log(`订单状态:${order.status}`);
console.log(`支付状态:${order.paymentStatus}`);
console.log(`订单总额:$${order.totalAmount.toFixed(2)}`);
// 7. 查看用户订单
console.log("\n7. 查看用户订单...");
const userOrders = ecommerce.getUserOrders(user.id);
console.log("用户订单:");
userOrders.forEach(o => {
console.log(`- 订单ID: ${o.id}, 状态: ${o.status}, 总额: $${o.totalAmount.toFixed(2)}`);
});
// 8. 更新订单状态
console.log("\n8. 更新订单状态...");
if (order.status === 'processing') {
ecommerce.updateOrderStatus(order.id, 'shipped');
const updatedOrder = ecommerce.getOrder(order.id);
console.log(`订单状态已更新为:${updatedOrder?.status}`);
}
// 9. 用户登出
console.log("\n9. 用户登出...");
ecommerce.logout();
console.log("用户已登出");
console.log("\n====== 演示完成 ======");
}
// 运行演示
// runDemo();为了让我们的电子商务系统更加实用,让我们实现一个简单的命令行界面,让用户可以通过命令行与系统交互:
// 命令行界面实现
import * as readline from 'readline';
class ECommerceCLI {
private ecommerce: ECommerceSystem;
private rl: readline.Interface;
private currentUserId: string | null = null;
constructor(ecommerce: ECommerceSystem) {
this.ecommerce = ecommerce;
this.rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
prompt: '> '
});
}
// 启动命令行界面
start() {
console.log("欢迎使用简易电子商务系统!");
console.log("输入 'help' 查看可用命令。\n");
this.showMainMenu();
this.rl.prompt();
this.rl.on('line', (line) => {
const command = line.trim().toLowerCase();
this.handleCommand(command);
this.rl.prompt();
}).on('close', () => {
console.log('感谢使用简易电子商务系统,再见!');
process.exit(0);
});
}
// 处理用户命令
private handleCommand(command: string) {
const args = command.split(' ');
const mainCommand = args[0];
switch (mainCommand) {
case 'help':
this.showHelp();
break;
case 'menu':
if (this.currentUserId) {
this.showUserMenu();
} else {
this.showMainMenu();
}
break;
case 'register':
this.handleRegister();
break;
case 'login':
this.handleLogin();
break;
case 'logout':
this.handleLogout();
break;
case 'products':
this.listProducts();
break;
case 'product':
if (args.length > 1) {
this.showProductDetails(args[1]);
} else {
console.log("请提供产品ID。使用格式: product <productId>");
}
break;
case 'cart':
if (this.currentUserId) {
this.viewCart();
} else {
console.log("请先登录。");
}
break;
case 'add':
if (this.currentUserId && args.length > 2) {
this.addToCart(args[1], parseInt(args[2]));
} else if (!this.currentUserId) {
console.log("请先登录。");
} else {
console.log("使用格式: add <productId> <quantity>");
}
break;
case 'remove':
if (this.currentUserId && args.length > 1) {
this.removeFromCart(args[1]);
} else if (!this.currentUserId) {
console.log("请先登录。");
} else {
console.log("使用格式: remove <productId>");
}
break;
case 'update':
if (this.currentUserId && args.length > 2) {
this.updateCartItem(args[1], parseInt(args[2]));
} else if (!this.currentUserId) {
console.log("请先登录。");
} else {
console.log("使用格式: update <productId> <quantity>");
}
break;
case 'checkout':
if (this.currentUserId) {
this.checkout();
} else {
console.log("请先登录。");
}
break;
case 'orders':
if (this.currentUserId) {
this.listOrders();
} else {
console.log("请先登录。");
}
break;
case 'order':
if (this.currentUserId && args.length > 1) {
this.showOrderDetails(args[1]);
} else if (!this.currentUserId) {
console.log("请先登录。");
} else {
console.log("使用格式: order <orderId>");
}
break;
case 'exit':
case 'quit':
this.rl.close();
break;
default:
console.log("未知命令。输入 'help' 查看可用命令。");
}
}
// 显示帮助信息
private showHelp() {
console.log("可用命令:");
console.log(" help - 显示帮助信息");
console.log(" menu - 显示主菜单");
console.log(" register - 注册新用户");
console.log(" login - 用户登录");
console.log(" logout - 用户登出");
console.log(" products - 列出所有产品");
console.log(" product <productId> - 查看产品详情");
console.log(" cart - 查看购物车");
console.log(" add <productId> <qty> - 添加商品到购物车");
console.log(" remove <productId> - 从购物车移除商品");
console.log(" update <productId> <qty> - 更新购物车中商品数量");
console.log(" checkout - 结账并创建订单");
console.log(" orders - 查看订单历史");
console.log(" order <orderId> - 查看订单详情");
console.log(" exit/quit - 退出系统");
}
// 显示主菜单
private showMainMenu() {
console.log("===== 主菜单 =====");
console.log("1. 注册 (register)");
console.log("2. 登录 (login)");
console.log("3. 浏览产品 (products)");
console.log("4. 帮助 (help)");
console.log("5. 退出 (exit)");
console.log("=================");
}
// 显示用户菜单
private showUserMenu() {
console.log("===== 用户菜单 =====");
console.log("1. 浏览产品 (products)");
console.log("2. 查看购物车 (cart)");
console.log("3. 查看订单历史 (orders)");
console.log("4. 帮助 (help)");
console.log("5. 登出 (logout)");
console.log("==================");
}
// 处理用户注册
private handleRegister() {
this.rl.question('请输入用户名: ', (username) => {
this.rl.question('请输入邮箱: ', (email) => {
this.rl.question('请输入密码: ', (password) => {
this.rl.question('请输入全名: ', (fullName) => {
this.rl.question('请输入地址: ', (address) => {
this.rl.question('请输入电话: ', (phone) => {
const user = this.ecommerce.registerUser({
username,
email,
password,
fullName,
address,
phone
});
if (user) {
console.log(`注册成功!用户ID: ${user.id}`);
} else {
console.log("注册失败!用户名或邮箱已被使用。");
}
this.rl.prompt();
});
});
});
});
});
});
}
// 处理用户登录
private handleLogin() {
this.rl.question('请输入用户名: ', (username) => {
this.rl.question('请输入密码: ', (password) => {
const user = this.ecommerce.login(username, password);
if (user) {
console.log(`登录成功!欢迎回来,${user.fullName}!`);
this.currentUserId = user.id;
this.showUserMenu();
} else {
console.log("登录失败!用户名或密码错误。");
}
this.rl.prompt();
});
});
}
// 处理用户登出
private handleLogout() {
this.ecommerce.logout();
this.currentUserId = null;
console.log("已成功登出。");
this.showMainMenu();
}
// 列出所有产品
private listProducts() {
const products = this.ecommerce.getAllProducts();
if (products.length === 0) {
console.log("暂无产品。");
return;
}
console.log("产品列表:");
products.forEach((product, index) => {
console.log(`${index + 1}. ${product.name} - $${product.price.toFixed(2)} (ID: ${product.id})`);
console.log(` ${product.description.substring(0, 50)}...`);
console.log(` 分类: ${product.category}`);
});
}
// 显示产品详情
private showProductDetails(productId: string) {
const product = this.ecommerce.getProduct(productId);
if (!product) {
console.log("未找到该产品。");
return;
}
console.log(`产品详情 (ID: ${product.id})`);
console.log(`名称: ${product.name}`);
console.log(`价格: $${product.price.toFixed(2)}`);
console.log(`分类: ${product.category}`);
console.log(`描述: ${product.description}`);
console.log(`图片数量: ${product.images.length}`);
}
// 查看购物车
private viewCart() {
if (!this.currentUserId) {
console.log("请先登录。");
return;
}
const cartItems = this.ecommerce.viewCart(this.currentUserId);
if (cartItems.length === 0) {
console.log("您的购物车是空的。");
return;
}
console.log("购物车:");
cartItems.forEach((item, index) => {
console.log(`${index + 1}. ${item.product.name} x ${item.quantity} - $${item.subtotal.toFixed(2)}`);
});
const total = this.ecommerce.calculateCartTotal(this.currentUserId);
console.log(`总计: $${total.toFixed(2)}`);
}
// 添加商品到购物车
private addToCart(productId: string, quantity: number) {
if (!this.currentUserId) {
console.log("请先登录。");
return;
}
const success = this.ecommerce.addToCart(this.currentUserId, productId, quantity);
if (success) {
console.log("商品已成功添加到购物车。");
} else {
console.log("添加失败!产品不存在或库存不足。");
}
}
// 从购物车移除商品
private removeFromCart(productId: string) {
if (!this.currentUserId) {
console.log("请先登录。");
return;
}
const success = this.ecommerce.removeFromCart(this.currentUserId, productId);
if (success) {
console.log("商品已从购物车移除。");
} else {
console.log("移除失败!购物车中不存在该商品。");
}
}
// 更新购物车中商品数量
private updateCartItem(productId: string, quantity: number) {
if (!this.currentUserId) {
console.log("请先登录。");
return;
}
const success = this.ecommerce.updateCartItem(this.currentUserId, productId, quantity);
if (success) {
console.log("购物车商品数量已更新。");
} else {
console.log("更新失败!产品不存在或库存不足。");
}
}
// 结账并创建订单
private checkout() {
if (!this.currentUserId) {
console.log("请先登录。");
return;
}
this.rl.question('请确认收货地址: ', (shippingAddress) => {
this.rl.question('请选择支付方式 (online/cod): ', (paymentMethod) => {
const order = this.ecommerce.createOrder(this.currentUserId!, shippingAddress, paymentMethod);
if (order) {
console.log(`订单已创建!订单ID: ${order.id}`);
console.log(`订单总额: $${order.totalAmount.toFixed(2)}`);
console.log(`订单状态: ${order.status}`);
console.log(`支付状态: ${order.paymentStatus}`);
} else {
console.log("创建订单失败!您的购物车可能为空或库存不足。");
}
this.rl.prompt();
});
});
}
// 列出所有订单
private listOrders() {
if (!this.currentUserId) {
console.log("请先登录。");
return;
}
const orders = this.ecommerce.getUserOrders(this.currentUserId);
if (orders.length === 0) {
console.log("您暂无订单。");
return;
}
console.log("订单列表:");
orders.forEach((order, index) => {
console.log(`${index + 1}. 订单ID: ${order.id}`);
console.log(` 总额: $${order.totalAmount.toFixed(2)}`);
console.log(` 状态: ${order.status}`);
console.log(` 支付状态: ${order.paymentStatus}`);
console.log(` 创建时间: ${order.createdAt.toLocaleString()}`);
});
}
// 显示订单详情
private showOrderDetails(orderId: string) {
if (!this.currentUserId) {
console.log("请先登录。");
return;
}
const order = this.ecommerce.getOrder(orderId);
if (!order || order.userId !== this.currentUserId) {
console.log("未找到该订单。");
return;
}
console.log(`订单详情 (ID: ${order.id})`);
console.log(`总额: $${order.totalAmount.toFixed(2)}`);
console.log(`状态: ${order.status}`);
console.log(`支付状态: ${order.paymentStatus}`);
console.log(`支付方式: ${order.paymentMethod}`);
console.log(`收货地址: ${order.shippingAddress}`);
console.log(`创建时间: ${order.createdAt.toLocaleString()}`);
console.log(`更新时间: ${order.updatedAt.toLocaleString()}`);
console.log("订单项:");
order.items.forEach((item, index) => {
const product = this.ecommerce.getProduct(item.productId);
const productName = product ? product.name : "[已删除产品]";
console.log(`${index + 1}. ${productName} x ${item.quantity} - $${(item.priceAtPurchase * item.quantity).toFixed(2)}`);
});
}
}
// 创建命令行界面实例并启动
// const cli = new ECommerceCLI(ecommerce);
// cli.start();现在,让我们添加项目构建和运行指南:
ecommerce-system/
├── src/
│ ├── index.ts
│ ├── models/
│ │ └── index.ts
│ ├── services/
│ │ ├── ProductService.ts
│ │ ├── CartService.ts
│ │ ├── UserService.ts
│ │ ├── OrderService.ts
│ │ ├── PaymentService.ts
│ │ ├── InventoryService.ts
│ │ └── NotificationService.ts
│ └── cli/
│ └── ECommerceCLI.ts
├── package.json
└── tsconfig.jsonmkdir ecommerce-system
cd ecommerce-system
npm init -y
npm install typescript @types/node --save-dev
npx tsc --init{
"compilerOptions": {
"target": "ES2020",
"module": "CommonJS",
"rootDir": "./src",
"outDir": "./dist",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
}
}将上面实现的代码按照项目结构组织到相应的文件中。
npx tsc
node dist/index.js这个电子商务系统展示了以下TypeScript面向对象编程的核心概念和设计模式:
通过本教程,我们学习了TypeScript面向对象编程的核心概念和实践技巧。我们从基础的类和对象开始,逐步学习了继承、多态、抽象类、接口、访问修饰符、静态成员、单例模式、泛型等高级特性。
我们还探讨了如何利用AI辅助工具来提升TypeScript面向对象编程的学习效率,包括AI代码解释器、代码生成器、代码优化器、错误检测器和学习助手等。
最后,我们通过构建一个简单的电子商务系统,将所学的知识应用到了实际项目中。这个项目展示了如何使用TypeScript的面向对象编程特性来设计和实现一个具有良好结构和可扩展性的应用程序。
面向对象编程是TypeScript中的重要编程范式,掌握它将帮助你编写更加结构化、可维护和可扩展的代码。通过不断实践和探索,你将能够更加熟练地运用这些概念来解决实际问题。