3.1 接口深入
3.1.1 接口基础回顾
接口定义和使用
// 基本接口定义
interface Person {
name: string;
age: number;
email?: string; // 可选属性
readonly id: number; // 只读属性
}
// 实现接口
const person: Person = {
id: 1,
name: "Alice",
age: 30,
email: "alice@example.com"
};
// person.id = 2; // 错误:只读属性不能修改
函数类型接口
// 函数签名接口
interface SearchFunc {
(source: string, subString: string): boolean;
}
// 实现函数接口
const mySearch: SearchFunc = function(source: string, subString: string) {
return source.indexOf(subString) > -1;
};
// 方法签名接口
interface StringValidator {
isAcceptable(s: string): boolean;
errorMessage?: string;
}
class EmailValidator implements StringValidator {
errorMessage = "Invalid email format";
isAcceptable(s: string): boolean {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(s);
}
}
3.1.2 索引签名
字符串索引签名
// 字符串索引签名
interface StringDictionary {
[index: string]: string;
}
const dict: StringDictionary = {
name: "Alice",
city: "New York",
country: "USA"
};
// 混合固定属性和索引签名
interface Config {
name: string; // 固定属性
version: number; // 固定属性
[key: string]: any; // 索引签名
}
const config: Config = {
name: "MyApp",
version: 1.0,
debug: true,
apiUrl: "https://api.example.com",
timeout: 5000
};
数字索引签名
// 数字索引签名
interface NumberArray {
[index: number]: number;
length: number; // 数组都有length属性
}
const fibonacci: NumberArray = {
0: 1,
1: 1,
2: 2,
3: 3,
4: 5,
5: 8,
length: 6
};
// 同时使用字符串和数字索引
interface MixedArray {
[index: number]: string;
[index: string]: string | number;
length: number;
}
const mixedArray: MixedArray = {
0: "first",
1: "second",
2: "third",
length: 3,
name: "MyArray",
version: 1
};
3.1.3 接口继承
单继承
// 基础接口
interface Shape {
color: string;
area(): number;
}
// 继承接口
interface Circle extends Shape {
radius: number;
}
interface Rectangle extends Shape {
width: number;
height: number;
}
// 实现继承的接口
class CircleImpl implements Circle {
constructor(public color: string, public radius: number) {}
area(): number {
return Math.PI * this.radius ** 2;
}
}
class RectangleImpl implements Rectangle {
constructor(
public color: string,
public width: number,
public height: number
) {}
area(): number {
return this.width * this.height;
}
}
多重继承
// 多个基础接口
interface Flyable {
fly(): void;
altitude: number;
}
interface Swimmable {
swim(): void;
depth: number;
}
interface Walkable {
walk(): void;
speed: number;
}
// 多重继承
interface Duck extends Flyable, Swimmable, Walkable {
quack(): void;
}
// 实现多重继承的接口
class MallardDuck implements Duck {
altitude = 0;
depth = 0;
speed = 5;
fly(): void {
this.altitude = 100;
console.log("Flying at altitude", this.altitude);
}
swim(): void {
this.depth = 2;
console.log("Swimming at depth", this.depth);
}
walk(): void {
console.log("Walking at speed", this.speed);
}
quack(): void {
console.log("Quack!");
}
}
3.1.4 接口合并
声明合并
// 第一个接口声明
interface User {
name: string;
age: number;
}
// 第二个接口声明(合并)
interface User {
email: string;
isActive: boolean;
}
// 合并后的接口包含所有属性
const user: User = {
name: "Alice",
age: 30,
email: "alice@example.com",
isActive: true
};
// 模块扩展示例
declare global {
interface Window {
myCustomProperty: string;
}
}
// 现在可以使用扩展的属性
window.myCustomProperty = "Hello World";
命名空间合并
// 命名空间和接口合并
namespace Validation {
export interface StringValidator {
isAcceptable(s: string): boolean;
}
}
namespace Validation {
export interface StringValidator {
errorMessage: string;
}
export class LettersOnlyValidator implements StringValidator {
errorMessage = "Only letters are allowed";
isAcceptable(s: string): boolean {
return /^[A-Za-z]+$/.test(s);
}
}
}
// 使用合并后的接口
const validator: Validation.StringValidator = new Validation.LettersOnlyValidator();
3.2 类的基础
3.2.1 类的定义和实例化
基本类定义
// 基本类定义
class Person {
// 属性声明
name: string;
age: number;
private _id: number;
// 构造函数
constructor(name: string, age: number) {
this.name = name;
this.age = age;
this._id = Math.random();
}
// 方法
greet(): string {
return `Hello, I'm ${this.name} and I'm ${this.age} years old.`;
}
// getter
get id(): number {
return this._id;
}
// setter
set id(value: number) {
if (value > 0) {
this._id = value;
}
}
}
// 实例化
const person = new Person("Alice", 30);
console.log(person.greet());
console.log(person.id);
参数属性
// 参数属性简化写法
class Employee {
constructor(
public name: string,
public department: string,
private _salary: number,
protected employeeId: number
) {
// 构造函数体可以为空
// TypeScript会自动创建并初始化属性
}
get salary(): number {
return this._salary;
}
set salary(value: number) {
if (value > 0) {
this._salary = value;
}
}
getInfo(): string {
return `${this.name} works in ${this.department}`;
}
}
const employee = new Employee("Bob", "Engineering", 75000, 12345);
console.log(employee.getInfo());
3.2.2 访问修饰符
public、private、protected
class Animal {
public name: string; // 公共属性
private _age: number; // 私有属性
protected species: string; // 受保护属性
constructor(name: string, age: number, species: string) {
this.name = name;
this._age = age;
this.species = species;
}
// 公共方法
public makeSound(): void {
console.log("Some generic animal sound");
}
// 私有方法
private calculateLifeStage(): string {
if (this._age < 1) return "baby";
if (this._age < 3) return "young";
if (this._age < 10) return "adult";
return "senior";
}
// 受保护方法
protected getBasicInfo(): string {
return `${this.name} is a ${this.calculateLifeStage()} ${this.species}`;
}
// 公共方法访问私有和受保护成员
public getInfo(): string {
return this.getBasicInfo();
}
}
class Dog extends Animal {
constructor(name: string, age: number, public breed: string) {
super(name, age, "dog");
}
public makeSound(): void {
console.log("Woof!");
}
public getDetailedInfo(): string {
// 可以访问受保护成员
return `${this.getBasicInfo()} of breed ${this.breed}`;
// 不能访问私有成员
// return this._age; // 错误
}
}
const dog = new Dog("Buddy", 3, "Golden Retriever");
console.log(dog.name); // OK: public
console.log(dog.getInfo()); // OK: public method
// console.log(dog._age); // 错误: private
// console.log(dog.species); // 错误: protected
readonly修饰符
class Book {
readonly isbn: string;
readonly title: string;
public author: string;
private _publishDate: Date;
constructor(isbn: string, title: string, author: string) {
this.isbn = isbn; // 只能在构造函数中赋值
this.title = title;
this.author = author;
this._publishDate = new Date();
}
get publishDate(): Date {
return this._publishDate;
}
updateAuthor(newAuthor: string): void {
this.author = newAuthor; // OK: 不是readonly
// this.title = "New Title"; // 错误: readonly属性
}
}
const book = new Book("978-0123456789", "TypeScript Guide", "Alice");
console.log(book.isbn); // OK: 读取
// book.isbn = "new-isbn"; // 错误: readonly属性
3.2.3 静态成员
静态属性和方法
class MathUtils {
// 静态属性
static readonly PI = 3.14159;
static readonly E = 2.71828;
private static instanceCount = 0;
// 实例属性
public id: number;
constructor() {
MathUtils.instanceCount++;
this.id = MathUtils.instanceCount;
}
// 静态方法
static add(a: number, b: number): number {
return a + b;
}
static multiply(a: number, b: number): number {
return a * b;
}
static circleArea(radius: number): number {
return MathUtils.PI * radius * radius;
}
static getInstanceCount(): number {
return MathUtils.instanceCount;
}
// 实例方法
getInstanceId(): number {
return this.id;
}
}
// 使用静态成员
console.log(MathUtils.PI); // 3.14159
console.log(MathUtils.add(5, 3)); // 8
console.log(MathUtils.circleArea(5)); // 78.5395
// 创建实例
const math1 = new MathUtils();
const math2 = new MathUtils();
console.log(math1.getInstanceId()); // 1
console.log(math2.getInstanceId()); // 2
console.log(MathUtils.getInstanceCount()); // 2
静态块
class DatabaseConnection {
private static instance: DatabaseConnection;
private static isInitialized = false;
private constructor(private connectionString: string) {}
// 静态初始化块(TypeScript 4.4+)
static {
console.log("Initializing DatabaseConnection class");
// 执行静态初始化逻辑
}
static getInstance(connectionString?: string): DatabaseConnection {
if (!DatabaseConnection.instance) {
if (!connectionString) {
throw new Error("Connection string required for first instance");
}
DatabaseConnection.instance = new DatabaseConnection(connectionString);
DatabaseConnection.isInitialized = true;
}
return DatabaseConnection.instance;
}
connect(): void {
console.log(`Connecting to ${this.connectionString}`);
}
static isReady(): boolean {
return DatabaseConnection.isInitialized;
}
}
// 单例模式使用
const db1 = DatabaseConnection.getInstance("mongodb://localhost:27017");
const db2 = DatabaseConnection.getInstance(); // 不需要再传参数
console.log(db1 === db2); // true
3.3 继承
3.3.1 类继承基础
extends关键字
// 基类
class Vehicle {
protected brand: string;
protected year: number;
private _mileage: number = 0;
constructor(brand: string, year: number) {
this.brand = brand;
this.year = year;
}
start(): void {
console.log(`${this.brand} is starting...`);
}
stop(): void {
console.log(`${this.brand} is stopping...`);
}
get mileage(): number {
return this._mileage;
}
protected addMileage(miles: number): void {
this._mileage += miles;
}
getInfo(): string {
return `${this.year} ${this.brand}`;
}
}
// 派生类
class Car extends Vehicle {
private doors: number;
constructor(brand: string, year: number, doors: number) {
super(brand, year); // 调用父类构造函数
this.doors = doors;
}
// 重写父类方法
start(): void {
console.log("Checking engine...");
super.start(); // 调用父类方法
console.log("Car is ready to drive!");
}
// 新增方法
drive(miles: number): void {
console.log(`Driving ${miles} miles...`);
this.addMileage(miles); // 调用受保护方法
}
// 重写getInfo方法
getInfo(): string {
return `${super.getInfo()} with ${this.doors} doors`;
}
}
class Motorcycle extends Vehicle {
private engineSize: number;
constructor(brand: string, year: number, engineSize: number) {
super(brand, year);
this.engineSize = engineSize;
}
start(): void {
console.log("Kick starting...");
super.start();
console.log("Motorcycle is ready to ride!");
}
ride(miles: number): void {
console.log(`Riding ${miles} miles...`);
this.addMileage(miles);
}
getInfo(): string {
return `${super.getInfo()} with ${this.engineSize}cc engine`;
}
}
// 使用继承
const car = new Car("Toyota", 2022, 4);
const motorcycle = new Motorcycle("Honda", 2021, 600);
car.start();
car.drive(100);
console.log(car.getInfo());
console.log(`Car mileage: ${car.mileage}`);
motorcycle.start();
motorcycle.ride(50);
console.log(motorcycle.getInfo());
console.log(`Motorcycle mileage: ${motorcycle.mileage}`);
3.3.2 方法重写和super关键字
方法重写
class Shape {
protected name: string;
constructor(name: string) {
this.name = name;
}
// 基类方法
area(): number {
return 0;
}
perimeter(): number {
return 0;
}
describe(): string {
return `This is a ${this.name} with area ${this.area()} and perimeter ${this.perimeter()}`;
}
}
class Circle extends Shape {
constructor(private radius: number) {
super("circle");
}
// 重写area方法
area(): number {
return Math.PI * this.radius ** 2;
}
// 重写perimeter方法
perimeter(): number {
return 2 * Math.PI * this.radius;
}
}
class Rectangle extends Shape {
constructor(private width: number, private height: number) {
super("rectangle");
}
area(): number {
return this.width * this.height;
}
perimeter(): number {
return 2 * (this.width + this.height);
}
// 重写describe方法,添加额外信息
describe(): string {
const baseDescription = super.describe();
return `${baseDescription}. Dimensions: ${this.width} x ${this.height}`;
}
}
// 多态性演示
const shapes: Shape[] = [
new Circle(5),
new Rectangle(4, 6),
new Circle(3)
];
shapes.forEach(shape => {
console.log(shape.describe());
});
3.3.3 抽象类
抽象类定义
// 抽象类
abstract class Animal {
protected name: string;
protected 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.`);
}
// 抽象方法 - 必须在子类中实现
abstract makeSound(): void;
abstract move(): void;
// 抽象getter
abstract get species(): string;
// 具体方法可以调用抽象方法
introduce(): void {
console.log(`I am ${this.name}, a ${this.species}. I am ${this.age} years old.`);
this.makeSound();
}
}
// 具体实现类
class Dog extends Animal {
constructor(name: string, age: number, private breed: string) {
super(name, age);
}
makeSound(): void {
console.log("Woof! Woof!");
}
move(): void {
console.log(`${this.name} is running.`);
}
get species(): string {
return "dog";
}
// 额外方法
fetch(): void {
console.log(`${this.name} is fetching the ball.`);
}
}
class Cat extends Animal {
constructor(name: string, age: number) {
super(name, age);
}
makeSound(): void {
console.log("Meow!");
}
move(): void {
console.log(`${this.name} is sneaking quietly.`);
}
get species(): string {
return "cat";
}
climb(): void {
console.log(`${this.name} is climbing a tree.`);
}
}
// 使用抽象类
// const animal = new Animal("Generic", 1); // 错误:不能实例化抽象类
const dog = new Dog("Buddy", 3, "Golden Retriever");
const cat = new Cat("Whiskers", 2);
dog.introduce();
dog.move();
dog.fetch();
cat.introduce();
cat.move();
cat.climb();
// 多态性
const animals: Animal[] = [dog, cat];
animals.forEach(animal => {
animal.eat();
animal.makeSound();
animal.move();
});
抽象类 vs 接口
// 接口定义契约
interface Flyable {
fly(): void;
altitude: number;
}
interface Swimmable {
swim(): void;
depth: number;
}
// 抽象类提供部分实现
abstract class Bird implements Flyable {
protected name: string;
public altitude: number = 0;
constructor(name: string) {
this.name = name;
}
// 接口方法的具体实现
fly(): void {
this.altitude = 100;
console.log(`${this.name} is flying at ${this.altitude} feet.`);
}
// 抽象方法
abstract makeSound(): void;
abstract buildNest(): void;
}
// 同时继承抽象类和实现接口
class Duck extends Bird implements Swimmable {
public depth: number = 0;
constructor(name: string) {
super(name);
}
makeSound(): void {
console.log("Quack!");
}
buildNest(): void {
console.log(`${this.name} is building a nest near water.`);
}
swim(): void {
this.depth = 3;
console.log(`${this.name} is swimming at ${this.depth} feet deep.`);
}
}
class Eagle extends Bird {
constructor(name: string) {
super(name);
}
makeSound(): void {
console.log("Screech!");
}
buildNest(): void {
console.log(`${this.name} is building a nest on a cliff.`);
}
hunt(): void {
console.log(`${this.name} is hunting for prey.`);
}
}
const duck = new Duck("Donald");
const eagle = new Eagle("Freedom");
duck.fly();
duck.swim();
duck.makeSound();
eagle.fly();
eagle.hunt();
eagle.makeSound();
3.4 类实现接口
3.4.1 implements关键字
基本接口实现
// 定义接口
interface Drivable {
speed: number;
start(): void;
stop(): void;
accelerate(amount: number): void;
}
interface Maintainable {
lastMaintenanceDate: Date;
performMaintenance(): void;
needsMaintenance(): boolean;
}
// 类实现单个接口
class Car implements Drivable {
speed: number = 0;
start(): void {
console.log("Car engine started");
}
stop(): void {
this.speed = 0;
console.log("Car stopped");
}
accelerate(amount: number): void {
this.speed += amount;
console.log(`Car accelerated to ${this.speed} mph`);
}
}
// 类实现多个接口
class Truck implements Drivable, Maintainable {
speed: number = 0;
lastMaintenanceDate: Date = new Date();
private mileage: number = 0;
start(): void {
console.log("Truck engine started");
}
stop(): void {
this.speed = 0;
console.log("Truck stopped");
}
accelerate(amount: number): void {
this.speed += amount;
this.mileage += amount * 0.1; // 假设的里程计算
console.log(`Truck accelerated to ${this.speed} mph`);
}
performMaintenance(): void {
this.lastMaintenanceDate = new Date();
console.log("Truck maintenance completed");
}
needsMaintenance(): boolean {
const daysSinceLastMaintenance =
(Date.now() - this.lastMaintenanceDate.getTime()) / (1000 * 60 * 60 * 24);
return daysSinceLastMaintenance > 30 || this.mileage > 1000;
}
}
接口继承和类实现
// 基础接口
interface Vehicle {
brand: string;
year: number;
start(): void;
}
// 扩展接口
interface ElectricVehicle extends Vehicle {
batteryLevel: number;
charge(): void;
}
interface AutonomousVehicle extends Vehicle {
autopilotEnabled: boolean;
enableAutopilot(): void;
disableAutopilot(): void;
}
// 多重接口继承
interface SmartElectricVehicle extends ElectricVehicle, AutonomousVehicle {
softwareVersion: string;
updateSoftware(): void;
}
// 实现复杂接口
class Tesla implements SmartElectricVehicle {
brand: string = "Tesla";
year: number;
batteryLevel: number = 100;
autopilotEnabled: boolean = false;
softwareVersion: string = "2023.1.0";
constructor(year: number) {
this.year = year;
}
start(): void {
console.log("Tesla started silently");
}
charge(): void {
this.batteryLevel = 100;
console.log("Tesla fully charged");
}
enableAutopilot(): void {
this.autopilotEnabled = true;
console.log("Autopilot enabled");
}
disableAutopilot(): void {
this.autopilotEnabled = false;
console.log("Autopilot disabled");
}
updateSoftware(): void {
this.softwareVersion = "2023.2.0";
console.log(`Software updated to ${this.softwareVersion}`);
}
}
3.4.2 接口约束类的结构
构造函数接口
// 构造函数接口
interface Constructable {
new (name: string): any;
}
interface ClockConstructor {
new (hour: number, minute: number): ClockInterface;
}
interface ClockInterface {
currentTime: Date;
tick(): void;
}
// 工厂函数使用构造函数接口
function createClock(
ctor: ClockConstructor,
hour: number,
minute: number
): ClockInterface {
return new ctor(hour, minute);
}
class DigitalClock implements ClockInterface {
currentTime: Date;
constructor(hour: number, minute: number) {
this.currentTime = new Date();
this.currentTime.setHours(hour, minute);
}
tick(): void {
console.log("Digital: " + this.currentTime.toLocaleTimeString());
}
}
class AnalogClock implements ClockInterface {
currentTime: Date;
constructor(hour: number, minute: number) {
this.currentTime = new Date();
this.currentTime.setHours(hour, minute);
}
tick(): void {
console.log("Analog: " + this.currentTime.toLocaleTimeString());
}
}
// 使用工厂函数
const digitalClock = createClock(DigitalClock, 10, 30);
const analogClock = createClock(AnalogClock, 14, 45);
digitalClock.tick();
analogClock.tick();
混合类型接口
// 混合类型接口(既是函数又是对象)
interface Counter {
(start: number): string;
interval: number;
reset(): void;
}
// 创建混合类型对象
function getCounter(): Counter {
const counter = function(start: number) {
return `Count: ${start}`;
} as Counter;
counter.interval = 123;
counter.reset = function() {
console.log("Counter reset");
};
return counter;
}
const myCounter = getCounter();
console.log(myCounter(10)); // "Count: 10"
console.log(myCounter.interval); // 123
myCounter.reset(); // "Counter reset"
3.5 泛型类和接口
3.5.1 泛型接口
基本泛型接口
// 泛型接口
interface Container<T> {
value: T;
getValue(): T;
setValue(value: T): void;
}
// 实现泛型接口
class Box<T> implements Container<T> {
constructor(public value: T) {}
getValue(): T {
return this.value;
}
setValue(value: T): void {
this.value = value;
}
}
// 使用泛型类
const stringBox = new Box<string>("Hello");
const numberBox = new Box<number>(42);
const booleanBox = new Box<boolean>(true);
console.log(stringBox.getValue()); // "Hello"
console.log(numberBox.getValue()); // 42
console.log(booleanBox.getValue()); // true
// 复杂泛型接口
interface Repository<T, K> {
findById(id: K): T | null;
findAll(): T[];
save(entity: T): T;
delete(id: K): boolean;
}
interface User {
id: number;
name: string;
email: string;
}
class UserRepository implements Repository<User, number> {
private users: User[] = [];
private nextId = 1;
findById(id: number): User | null {
return this.users.find(user => user.id === id) || null;
}
findAll(): User[] {
return [...this.users];
}
save(user: User): User {
if (user.id === 0) {
user.id = this.nextId++;
this.users.push(user);
} else {
const index = this.users.findIndex(u => u.id === user.id);
if (index >= 0) {
this.users[index] = user;
}
}
return user;
}
delete(id: number): boolean {
const index = this.users.findIndex(user => user.id === id);
if (index >= 0) {
this.users.splice(index, 1);
return true;
}
return false;
}
}
3.5.2 泛型类
基本泛型类
// 泛型类
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 = [];
}
toArray(): T[] {
return [...this.items];
}
}
// 使用泛型类
const numberStack = new Stack<number>();
numberStack.push(1);
numberStack.push(2);
numberStack.push(3);
console.log(numberStack.peek()); // 3
console.log(numberStack.pop()); // 3
console.log(numberStack.size()); // 2
const stringStack = new Stack<string>();
stringStack.push("hello");
stringStack.push("world");
console.log(stringStack.toArray()); // ["hello", "world"]
泛型约束
// 泛型约束
interface Lengthwise {
length: number;
}
class LengthProcessor<T extends Lengthwise> {
process(arg: T): T {
console.log(`Processing item with length: ${arg.length}`);
return arg;
}
}
const processor = new LengthProcessor();
processor.process("hello"); // OK: string has length
processor.process([1, 2, 3]); // OK: array has length
processor.process({ length: 10 }); // OK: object has length
// processor.process(123); // 错误: number没有length属性
// 键约束
class KeyValueStore<T, K extends keyof T> {
private data: T;
constructor(data: T) {
this.data = data;
}
get(key: K): T[K] {
return this.data[key];
}
set(key: K, value: T[K]): void {
this.data[key] = value;
}
}
interface Person {
name: string;
age: number;
email: string;
}
const person: Person = {
name: "Alice",
age: 30,
email: "alice@example.com"
};
const store = new KeyValueStore(person);
console.log(store.get("name")); // "Alice"
store.set("age", 31);
console.log(store.get("age")); // 31
// store.get("invalid"); // 错误: "invalid"不是Person的键
3.6 装饰器(实验性功能)
3.6.1 类装饰器
基本类装饰器
// 启用装饰器支持需要在tsconfig.json中设置
// "experimentalDecorators": true
// 类装饰器
function sealed(constructor: Function) {
Object.seal(constructor);
Object.seal(constructor.prototype);
}
function logged<T extends { new (...args: any[]): {} }>(constructor: T) {
return class extends constructor {
constructor(...args: any[]) {
console.log(`Creating instance of ${constructor.name}`);
super(...args);
}
};
}
@sealed
@logged
class Person {
constructor(public name: string, public age: number) {}
greet() {
return `Hello, I'm ${this.name}`;
}
}
const person = new Person("Alice", 30); // 输出: Creating instance of Person
console.log(person.greet());
3.6.2 方法装饰器
方法装饰器示例
// 方法装饰器
function measure(target: any, propertyName: string, descriptor: PropertyDescriptor) {
const method = descriptor.value;
descriptor.value = function (...args: any[]) {
const start = performance.now();
const result = method.apply(this, args);
const end = performance.now();
console.log(`${propertyName} took ${end - start} milliseconds`);
return result;
};
}
function validate(target: any, propertyName: string, descriptor: PropertyDescriptor) {
const method = descriptor.value;
descriptor.value = function (...args: any[]) {
if (args.some(arg => arg == null)) {
throw new Error(`Invalid arguments for ${propertyName}`);
}
return method.apply(this, args);
};
}
class Calculator {
@measure
@validate
add(a: number, b: number): number {
return a + b;
}
@measure
multiply(a: number, b: number): number {
return a * b;
}
}
const calc = new Calculator();
console.log(calc.add(5, 3)); // 输出执行时间和结果
console.log(calc.multiply(4, 6)); // 输出执行时间和结果
// calc.add(null, 3); // 抛出验证错误
3.6.3 属性装饰器
属性装饰器示例
// 属性装饰器
function readonly(target: any, propertyName: string) {
Object.defineProperty(target, propertyName, {
writable: false
});
}
function format(formatString: string) {
return function (target: any, propertyName: string) {
let value: string;
const getter = function () {
return value;
};
const setter = function (newVal: string) {
value = formatString.replace('%s', newVal);
};
Object.defineProperty(target, propertyName, {
get: getter,
set: setter,
enumerable: true,
configurable: true
});
};
}
class User {
@readonly
id: number = Math.random();
@format("Hello, %s!")
name: string;
constructor(name: string) {
this.name = name;
}
}
const user = new User("Alice");
console.log(user.name); // "Hello, Alice!"
// user.id = 123; // 错误:只读属性
本章练习
练习1:接口设计
- 设计一个图书管理系统的接口结构
- 包含图书、作者、借阅者等接口
- 实现接口继承和组合
练习2:类继承
- 创建动物类层次结构
- 实现抽象基类和具体子类
- 演示多态性的使用
练习3:泛型应用
- 实现一个通用的数据访问层
- 创建泛型集合类
- 使用泛型约束确保类型安全
练习4:装饰器实践
- 创建日志装饰器
- 实现缓存装饰器
- 设计验证装饰器
练习5:综合项目
- 设计一个简单的电商系统
- 包含商品、订单、用户等类
- 使用接口、继承、泛型等特性
本章总结
在本章中,我们深入学习了TypeScript的面向对象编程特性:
- 接口深入:掌握了接口的高级用法,包括继承、合并等
- 类的基础:学会了类的定义、访问修饰符、静态成员等
- 继承机制:理解了类继承、方法重写、抽象类等概念
- 接口实现:掌握了类实现接口的方法和约束
- 泛型应用:学会了在类和接口中使用泛型
- 装饰器:了解了装饰器的基本用法(实验性功能)
下一章我们将学习TypeScript的泛型编程,这是TypeScript类型系统的高级特性。