MST

星途 面试题库

面试题:TypeScript类装饰器的元编程应用

使用TypeScript类装饰器实现一个简单的依赖注入功能。假设有`ServiceA`和`ServiceB`两个服务类,以及一个`App`类,`App`类依赖`ServiceA`和`ServiceB`。请通过类装饰器实现将`ServiceA`和`ServiceB`的实例注入到`App`类中,要求考虑装饰器的复用性和灵活性,给出完整且优化的代码示例,并简要说明设计思路。
18.6万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

代码示例

// 定义服务类
class ServiceA {
    public doSomething() {
        return 'ServiceA is doing something';
    }
}

class ServiceB {
    public doAnotherThing() {
        return 'ServiceB is doing another thing';
    }
}

// 依赖注入装饰器
function injectServices(...services: any[]) {
    return function (target: any) {
        for (let i = 0; i < services.length; i++) {
            const service = new services[i]();
            Object.defineProperty(target.prototype, services[i].name, {
                value: service,
                enumerable: true,
                writable: true,
                configurable: true
            });
        }
    };
}

// App类使用依赖注入装饰器
@injectServices(ServiceA, ServiceB)
class App {
    private serviceA: ServiceA;
    private serviceB: ServiceB;

    constructor() {
        // 这里不需要手动实例化ServiceA和ServiceB,装饰器已经注入
    }

    public run() {
        console.log(this.serviceA.doSomething());
        console.log(this.serviceB.doAnotherThing());
    }
}

// 使用App类
const app = new App();
app.run();

设计思路

  1. 定义服务类:首先定义ServiceAServiceB两个服务类,它们各自有自己的功能方法。
  2. 创建依赖注入装饰器injectServices装饰器接收多个服务类作为参数。在装饰器内部,遍历传入的服务类,创建每个服务类的实例,并通过Object.defineProperty将实例添加到目标类(App类)的原型上,这样目标类的实例就可以访问到这些注入的服务实例。
  3. 应用装饰器:在App类上使用@injectServices(ServiceA, ServiceB)装饰器,这样在App类实例化时,ServiceAServiceB的实例就会被注入到App类实例中。
  4. 使用注入的服务App类的run方法中可以直接使用注入的serviceAserviceB实例调用其方法,完成依赖的功能。这种设计方式保证了装饰器的复用性和灵活性,只需要在需要依赖注入的类上使用装饰器并传入相应的服务类即可。