首页 > 解决方案 > 使用接口的 Typescript 依赖反转

问题描述

我在 TypeScript 中有一个名为UsersUseCases

import UsersRepository from './UsersRepository';

class UsersUseCases{
    private userRepository:IUsersRepository;

    constructor(receivedUsersRepository:any = null){
        this.userRepository =
            receivedUsersRepository === null ? new UsersRepository() : new receivedUsersRepository();
   }

   /** other methods **/
}

我的目标是在定义要使用的默认存储库的同时使用依赖注入这样,我在真正运行代码时userRepository不需要传递 a ,而只需要在我的测试中传递。receivedUsersRepository有更好的方法吗?

的代码IUsersRepository

export interface IUsersRepository {
    createUser(email: string, password: string): Promise<any>;
}

的代码UsersRepository

class UsersRepository implements IUsersRepository {  
    async createUser(email: string, password: string) {
        /** Implementation **/
    }
}

export default UsersRepository;

我试过以下代码:

import UsersRepository from './UsersRepository';

class UsersUseCases{
    private userRepository:IUsersRepository;

    constructor(ReceivedUsersRepository: IUsersRepository | null = null) {
        this.userRepository =
        ReceivedUsersRepository === null ? new UsersRepository() : new ReceivedUsersRepository();
    }

   /** other methods **/
}

但我有以下错误:

此表达式不可构造。类型“IUsersRepository”没有构造 signatures.ts(2351)

对不起我的英语不好。我不是母语人士。

标签: typescriptclassdependency-injection

解决方案


如果问题是关于如何解决您的错误(而不主要是关于依赖注入),那么您应该了解构造签名receivedUsersRepository参数要么是,null要么是生成IUsersRepository实例的无参数构造函数。它本身不是一个IUsersRepository实例。因此IUsersRepository | null,您应该这样写,而不是 :

receivedUsersRepository: (new () => IUsersRepository) | null

然后您的代码将按需要工作:

constructor(receivedUsersRepository: (new () => IUsersRepository) | null) {
    this.userRepository =
        receivedUsersRepository === null ?
            new UsersRepository() : new receivedUsersRepository(); // okay
}

万岁。


当然,依赖注入意味着你总是在传递IUsersRepository,即使在真正运行代码时也是如此。这是一个外部服务。而且您绝对不会在课堂上构建该服务。所以做“真正的”依赖注入看起来更像

class UsersUseCases {
    constructor(private userRepositoryService: IUsersRepository) { }
    /** other methods **/
}

然后你的测试代码可能看起来像

const mockUsersRepository = {
    async createUser(email: string, password: string) {
        console.log("I'M NOT REALLY DOING IT");
    }
}
const testUsersUseCases = new UsersUseCases(mockUsersRepository);

而你的真实代码看起来像

const userRepo = new UsersRepository();
const usersUseCases = new UsersUseCases(userRepo);

Playground 代码链接


推荐阅读