Skip to content

Abstract Classes

abstracts/AbstractUserRepository.ts
export abstract class AbstractUserRepository {
abstract findById(id: string): Promise<User | null>;
protected log(message: string): void {
console.log(`[UserRepo] ${message}`);
}
}
// implementations/UserRepository.ts
export class UserRepository extends AbstractUserRepository {
async findById(id: string): Promise<User | null> {
this.log(`Finding user ${id}`);
// ... implementation
}
}
// use-cases/ProductUseCase.ts
export class ProductUseCase {
constructor(
private productRepo: AbstractProductRepository,
private userRepo: AbstractUserRepository // Cross-module!
) {}
}
Terminal window
npx @notjustcoders/ioc-arise generate

container.gen.d.ts:

export interface ContainerRegistry {
'AbstractUserRepository': UserRepository;
'AbstractProductRepository': ProductRepository;
'ProductUseCase': ProductUseCase;
}

container.gen.ts:

import { Container, Lifecycle } from '@notjustcoders/di-container';
import type { ContainerRegistry } from './container.gen.d';
import { UserRepository } from './implementations/UserRepository';
import { ProductRepository } from './implementations/ProductRepository';
import { ProductUseCase } from './use-cases/ProductUseCase';
export const container = new Container<ContainerRegistry>();
// Abstract class registered with concrete implementation
container.register('AbstractUserRepository', {
useClass: UserRepository,
lifecycle: Lifecycle.Singleton
});
container.register('AbstractProductRepository', {
useClass: ProductRepository,
lifecycle: Lifecycle.Singleton
});
container.register('ProductUseCase', {
useClass: ProductUseCase,
dependencies: ['AbstractProductRepository', 'AbstractUserRepository'],
lifecycle: Lifecycle.Singleton
});
import { container } from './container.gen';
// Resolve by abstract class name
const userRepo = container.resolve('AbstractUserRepository');
// ^? UserRepository - Full type safety!
const productUseCase = container.resolve('ProductUseCase');