dependency injection in typescript using di-injectable library

In this article, we’ll explore the concept of dependency injection in TypeScript and how it can revolutionize our software development process using di-injectable library.

What is Dependency Injection?

Dependency injection is a design patte…


This content originally appeared on DEV Community and was authored by farajshuaib

In this article, we’ll explore the concept of dependency injection in TypeScript and how it can revolutionize our software development process using di-injectable library.

What is Dependency Injection?

Dependency injection is a design pattern that allows us to decouple components by injecting their dependencies from external sources rather than creating them internally. This approach promotes loose coupling, reusability, and testability in our codebase.

Constructor Injection

Constructor injection is one of the most common forms of dependency injection. It involves injecting dependencies through a class’s constructor. Let’s consider an example:

class UserService {
  constructor(private userRepository: UserRepository) {}

  getUser(id: string) {
    return this.userRepository.getUserById(id);
  }
}

class UserRepository {
  getUserById(id: string) {
    // Retrieve user from the database
  }
}

const userRepository = new UserRepository();
const userService = new UserService(userRepository);

In the above example, the UserService class depends on the UserRepository class. By passing an instance of UserRepository through the constructor, we establish the dependency between the two classes. This approach allows for easy swapping of different implementations of UserRepository, making our code more flexible and extensible.

Benefits of Dependency Injection

By embracing dependency injection, we unlock several benefits that greatly enhance our codebase:

  • Loose Coupling
    Dependency injection promotes loose coupling between components, as they depend on abstractions rather than concrete implementations. This enables us to swap out dependencies easily, facilitating code maintenance and scalability.

  • Reusability
    With dependency injection, we can create components with minimal dependencies, making them highly reusable in different contexts. By injecting specific implementations of dependencies, we can tailor the behavior of a component without modifying its code.

  • Testability
    Dependency injection greatly simplifies unit testing. By injecting mock or fake dependencies during testing, we can isolate components and verify their behavior independently. This leads to more reliable and maintainable test suites.

  • Flexibility and Extensibility
    Using dependency injection allows us to add new features or change existing ones without modifying the core implementation. By injecting new dependencies or modifying existing ones, we can extend the functionality of our codebase without introducing breaking changes.

lets make dependency injection easier by using DI-injectable library

DI-injectable library is a simple Dependency Injection (DI) library for TypeScript supporting Singleton and Transient service lifetimes.

Installation

First, install the package via npm or yarn:


npm install injectable

yarn add injectable

Usage

Setting Up Services

  • Define Services: Create your service classes and use the @Injectable decorator and use ServiceLifetime enum to register your services as Singleton or Transient..
  • Resolve Services: Use the ServiceProvider to resolve instances of your services.

Example

Let's walk through a complete example.

  1. Define Services Create some simple services and use the @Injectable decorator.
// src/services/logger.ts
import { Injectable } from 'di-injectable'; 

@Injectable(ServiceLifetime.Singleton)
export class Logger {
  log(message: string) {
    console.log(`Logger: ${message}`);
  }
}
// src/services/userService.ts
import { Injectable, Inject } from 'di-injectable';
import { Logger } from './logger';

@Injectable()
export class UserService {
  constructor(@Inject(Logger) private logger: Logger) {}

  getUser() {
    this.logger.log('Getting user...');
    return { id: 1, name: 'John Doe' };
  }
}
  1. Resolve Services Use the ServiceProvider to resolve instances of your services.
// src/app.ts
import { ServiceProvider } from 'di-injectable';
import { UserService } from './services/userService';

const serviceProvider = new ServiceProvider();

const userService = serviceProvider.resolve<UserService>(UserService);
const user = userService.getUser();
console.log(user);

Explanation

  • Defining Services:
    • The Logger service is a simple logger class.
    • The UserService class depends on the Logger service. The @Inject decorator is used to inject the Logger service
    • into the UserService constructor.
  • Registering Services:
    • We register the Logger service as a Singleton, meaning only one instance of Logger will be created and shared.
    • We register the UserService as a Transient by default, meaning a new instance of UserService will be created every time it is resolved.
  • Resolving Services:
    • We create a ServiceProvider instance.
    • We resolve an instance of UserService using the serviceProvider. The UserService will have the Logger instance injected into it due to the @Inject decorator.

Service Lifetimes

  • Singleton: Only one instance of the service is created and shared.
  • Transient: A new instance of the service is created every time it is requested.

API Reference

  • ServiceProvider:
    • resolve<T>(token: any): T: Resolves an instance of the service.
    • Injectable: Decorator to mark a class as injectable as register it.
    • Inject: Decorator to inject dependencies into the constructor.

Conclusion

Dependency injection is a powerful technique that improves code maintainability, testability, and flexibility. By leveraging constructor or property injection, we can create loosely coupled components that are highly reusable and easy to test.

As software engineers, embracing dependency injection in our TypeScript projects empowers us to write cleaner, more modular, and robust code. It enhances the scalability of our applications, enables efficient collaboration between team members, and simplifies the introduction of new features or changes.


This content originally appeared on DEV Community and was authored by farajshuaib


Print Share Comment Cite Upload Translate Updates
APA

farajshuaib | Sciencx (2024-06-29T19:35:43+00:00) dependency injection in typescript using di-injectable library. Retrieved from https://www.scien.cx/2024/06/29/dependency-injection-in-typescript-using-di-injectable-library/

MLA
" » dependency injection in typescript using di-injectable library." farajshuaib | Sciencx - Saturday June 29, 2024, https://www.scien.cx/2024/06/29/dependency-injection-in-typescript-using-di-injectable-library/
HARVARD
farajshuaib | Sciencx Saturday June 29, 2024 » dependency injection in typescript using di-injectable library., viewed ,<https://www.scien.cx/2024/06/29/dependency-injection-in-typescript-using-di-injectable-library/>
VANCOUVER
farajshuaib | Sciencx - » dependency injection in typescript using di-injectable library. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2024/06/29/dependency-injection-in-typescript-using-di-injectable-library/
CHICAGO
" » dependency injection in typescript using di-injectable library." farajshuaib | Sciencx - Accessed . https://www.scien.cx/2024/06/29/dependency-injection-in-typescript-using-di-injectable-library/
IEEE
" » dependency injection in typescript using di-injectable library." farajshuaib | Sciencx [Online]. Available: https://www.scien.cx/2024/06/29/dependency-injection-in-typescript-using-di-injectable-library/. [Accessed: ]
rf:citation
» dependency injection in typescript using di-injectable library | farajshuaib | Sciencx | https://www.scien.cx/2024/06/29/dependency-injection-in-typescript-using-di-injectable-library/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.