Z
ZHANK
实战技巧

TypeScript 设计模式

Builder 模式类型化、Strategy 模式、类型安全的事件系统

TypeScript 设计模式

TypeScript 的类型系统让经典设计模式更安全——Builder 链式调用、Strategy 类型约束、类型安全的事件系统。

学完本章你将: 掌握 Builder 模式类型化、Strategy 模式、类型安全事件。


Builder 模式

typescript
class RequestBuilder {
    private url: string = "";
    private method: string = "GET";
    private headers: Record<string, string> = {};

    setUrl(url: string): this { this.url = url; return this; }
    setMethod(method: string): this { this.method = method; return this; }
    setHeader(key: string, value: string): this {
        this.headers[key] = value; return this;
    }
    build() {
        return { url: this.url, method: this.method, headers: this.headers };
    }
}

const req = new RequestBuilder()
    .setUrl("/api/users")
    .setMethod("POST")
    .setHeader("Content-Type", "application/json")
    .build();

Strategy 模式(类型约束)

typescript
type PaymentStrategy = {
    pay(amount: number): Promise<boolean>;
};

class AliPay implements PaymentStrategy {
    async pay(amount: number) { /* ... */ return true; }
}

class WeChatPay implements PaymentStrategy {
    async pay(amount: number) { /* ... */ return true; }
}

class PaymentService {
    constructor(private strategy: PaymentStrategy) { }
    async checkout(amount: number) {
        return this.strategy.pay(amount);
    }
}

类型安全的事件系统

typescript
type EventMap = {
    userLogin: { userId: number; timestamp: Date };
    orderCreated: { orderId: string; amount: number };
};

class TypedEmitter<T extends Record<string, any>> {
    private handlers = new Map<keyof T, Set<Function>>();

    on<K extends keyof T>(event: K, handler: (data: T[K]) => void) {
        if (!this.handlers.has(event)) this.handlers.set(event, new Set());
        this.handlers.get(event)!.add(handler);
    }

    emit<K extends keyof T>(event: K, data: T[K]) {
        this.handlers.get(event)?.forEach(h => h(data));
    }
}

const emitter = new TypedEmitter<EventMap>();
emitter.on("userLogin", ({ userId, timestamp }) => {
    console.log(`用户 ${userId} 登录于 ${timestamp}`);
});