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:接口设计

  1. 设计一个图书管理系统的接口结构
  2. 包含图书、作者、借阅者等接口
  3. 实现接口继承和组合

练习2:类继承

  1. 创建动物类层次结构
  2. 实现抽象基类和具体子类
  3. 演示多态性的使用

练习3:泛型应用

  1. 实现一个通用的数据访问层
  2. 创建泛型集合类
  3. 使用泛型约束确保类型安全

练习4:装饰器实践

  1. 创建日志装饰器
  2. 实现缓存装饰器
  3. 设计验证装饰器

练习5:综合项目

  1. 设计一个简单的电商系统
  2. 包含商品、订单、用户等类
  3. 使用接口、继承、泛型等特性

本章总结

在本章中,我们深入学习了TypeScript的面向对象编程特性:

  1. 接口深入:掌握了接口的高级用法,包括继承、合并等
  2. 类的基础:学会了类的定义、访问修饰符、静态成员等
  3. 继承机制:理解了类继承、方法重写、抽象类等概念
  4. 接口实现:掌握了类实现接口的方法和约束
  5. 泛型应用:学会了在类和接口中使用泛型
  6. 装饰器:了解了装饰器的基本用法(实验性功能)

下一章我们将学习TypeScript的泛型编程,这是TypeScript类型系统的高级特性。