Architect-level TypeScript: design patterns, dependency injection, and real-world architecture.
Design patterns, dependency injection, and enterprise architecture patterns.
class Database {
private static instance: Database;
private constructor() {}
static getInstance(): Database {
if (!Database.instance) {
Database.instance = new Database();
}
return Database.instance;
}
query(sql: string): void {
console.log(\`Executing: \${sql}\`);
}
}interface Product { name: string; price: number; }
interface ProductFactory {
create(name: string, price: number): Product;
}
class DigitalProductFactory implements ProductFactory {
create(name: string, price: number): Product {
return { name, price, type: "digital" };
}
}
class PhysicalProductFactory implements ProductFactory {
create(name: string, price: number): Product {
return { name, price, type: "physical", weight: 0 };
}
}interface Observer<T> {
update(data: T): void;
}
class Subject<T> {
private observers: Observer<T>[] = [];
subscribe(observer: Observer<T>): void {
this.observers.push(observer);
}
unsubscribe(observer: Observer<T>): void {
this.observers = this.observers.filter(o => o !== observer);
}
notify(data: T): void {
this.observers.forEach(o => o.update(data));
}
}interface PaymentStrategy {
pay(amount: number): void;
}
class CreditCardPayment implements PaymentStrategy {
constructor(private cardNumber: string) {}
pay(amount: number) {
console.log(\`Paid \${amount} with card \${this.cardNumber}\`);
}
}
class PayPalPayment implements PaymentStrategy {
constructor(private email: string) {}
pay(amount: number) {
console.log(\`Paid \${amount} via PayPal: \${this.email}\`);
}
}
class PaymentProcessor {
constructor(private strategy: PaymentStrategy) {}
setStrategy(strategy: PaymentStrategy) { this.strategy = strategy; }
process(amount: number) { this.strategy.pay(amount); }
}Singleton: single Database instance
Factory: created Digital/Physical products
Observer: notified 3 subscribers
Strategy: CreditCard/PayPal payments
Design patterns complete!
Review feedback below
interface ILogger {
log(message: string): void;
error(message: string): void;
}
interface IUserRepository {
findById(id: string): Promise<User | null>;
save(user: User): Promise<void>;
}
interface IEmailService {
send(to: string, subject: string, body: string): Promise<void>;
}class ConsoleLogger implements ILogger {
log(message: string) { console.log(\`[LOG] \${message}\`); }
error(message: string) { console.error(\`[ERROR] \${message}\`); }
}
class UserRepository implements IUserRepository {
constructor(private logger: ILogger) {}
async findById(id: string): Promise<User | null> {
this.logger.log(\`Finding user: \${id}\`);
return { id, name: "John" };
}
async save(user: User): Promise<void> {
this.logger.log(\`Saving user: \${user.id}\`);
}
}type Constructor<T> = new (...args: any[]) => T;
class Container {
private services = new Map<string, any>();
register<T>(token: string, instance: T): void {
this.services.set(token, instance);
}
resolve<T>(token: string): T {
const service = this.services.get(token);
if (!service) throw new Error(\`Service not found: \${token}\`);
return service;
}
}const Injectable = (): ClassDecorator => {
return (target) => {
Reflect.defineMetadata("injectable", true, target);
};
};
const Inject = (token: string): ParameterDecorator => {
return (target, key, index) => {
const existing = Reflect.getMetadata("inject", target) || [];
existing.push({ index, token });
Reflect.defineMetadata("inject", existing, target);
};
};const container = new Container();
// Register services
container.register("ILogger", new ConsoleLogger());
container.register("IUserRepository",
new UserRepository(container.resolve("ILogger"))
);
// Resolve and use
const userRepo = container.resolve<IUserRepository>("IUserRepository");
await userRepo.findById("123");Container: registered 3 services
Resolved: ILogger, IUserRepository, IEmailService
Injection: constructor injection working
DI container complete!
interface IService { method(): void; }services.set(token, instance)services.get(token) as TReview feedback below
// Entity (database model)
interface UserEntity {
id: string;
email: string;
passwordHash: string;
createdAt: Date;
updatedAt: Date;
}
// DTO (Data Transfer Object)
interface CreateUserDTO {
email: string;
password: string;
}
interface UserResponseDTO {
id: string;
email: string;
createdAt: string;
}interface Repository<T, ID> {
findById(id: ID): Promise<T | null>;
findAll(): Promise<T[]>;
create(entity: Omit<T, "id">): Promise<T>;
update(id: ID, entity: Partial<T>): Promise<T>;
delete(id: ID): Promise<void>;
}
class UserRepository implements Repository<UserEntity, string> {
private users: Map<string, UserEntity> = new Map();
async findById(id: string): Promise<UserEntity | null> {
return this.users.get(id) ?? null;
}
// ... other methods
}class UserService {
constructor(
private userRepo: Repository<UserEntity, string>,
private emailService: IEmailService,
private logger: ILogger
) {}
async createUser(dto: CreateUserDTO): Promise<UserResponseDTO> {
this.logger.log(\`Creating user: \${dto.email}\`);
const entity = await this.userRepo.create({
email: dto.email,
passwordHash: await this.hashPassword(dto.password),
createdAt: new Date(),
updatedAt: new Date()
});
await this.emailService.send(dto.email, "Welcome!", "...");
return this.toDTO(entity);
}
private toDTO(entity: UserEntity): UserResponseDTO {
return {
id: entity.id,
email: entity.email,
createdAt: entity.createdAt.toISOString()
};
}
}class UserController {
constructor(private userService: UserService) {}
async handleCreateUser(req: Request): Promise<Response> {
try {
const dto: CreateUserDTO = req.body;
const user = await this.userService.createUser(dto);
return { status: 201, body: user };
} catch (error) {
return { status: 400, body: { error: error.message } };
}
}
}Entity/DTO: defined and mapped
Repository: CRUD operations
Service: business logic layer
Controller: HTTP handlers
Architecture complete!
Review feedback below