使用接口的 Typescript 依赖倒置
Typescript dependency invertion using interfaces
我在 TypeScript 中有一个 class 叫做 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
上使用 依赖注入 ,同时定义要使用的默认存储库。这样,当 运行 代码真实时,我不需要传递 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 **/
}
但是我遇到了以下错误:
This expression is not constructable. Type 'IUsersRepository' has no construct signatures.ts(2351)
对不起我的英语。我不是母语人士。
如果问题是关于如何解决您的错误(而不是主要关于依赖注入),那么您应该了解 construct signatures。 receivedUsersRepository
参数要么是 null
,要么是生成 IUsersRepository
实例的无参数构造函数。它本身不是 IUsersRepository
实例。所以你应该这样写而不是IUsersRepository | null
:
receivedUsersRepository: (new () => IUsersRepository) | null
然后您的代码将按预期运行:
constructor(receivedUsersRepository: (new () => IUsersRepository) | null) {
this.userRepository =
receivedUsersRepository === null ?
new UsersRepository() : new receivedUsersRepository(); // okay
}
万岁。
当然,dependency injection意味着你总是在传递IUsersRepository
,即使当运行代码是真实的。这是一个外部服务。而且您绝对不会 在 class 中构建 该服务。所以做“真正的”依赖注入看起来更像
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);
我在 TypeScript 中有一个 class 叫做 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
上使用 依赖注入 ,同时定义要使用的默认存储库。这样,当 运行 代码真实时,我不需要传递 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 **/
}
但是我遇到了以下错误:
This expression is not constructable. Type 'IUsersRepository' has no construct signatures.ts(2351)
对不起我的英语。我不是母语人士。
如果问题是关于如何解决您的错误(而不是主要关于依赖注入),那么您应该了解 construct signatures。 receivedUsersRepository
参数要么是 null
,要么是生成 IUsersRepository
实例的无参数构造函数。它本身不是 IUsersRepository
实例。所以你应该这样写而不是IUsersRepository | null
:
receivedUsersRepository: (new () => IUsersRepository) | null
然后您的代码将按预期运行:
constructor(receivedUsersRepository: (new () => IUsersRepository) | null) {
this.userRepository =
receivedUsersRepository === null ?
new UsersRepository() : new receivedUsersRepository(); // okay
}
万岁。
当然,dependency injection意味着你总是在传递IUsersRepository
,即使当运行代码是真实的。这是一个外部服务。而且您绝对不会 在 class 中构建 该服务。所以做“真正的”依赖注入看起来更像
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);