Last active
February 7, 2023 07:04
-
-
Save dimitrilahaye/9207ff38d4e2c732e0e32c779728c89b to your computer and use it in GitHub Desktop.
[Typescript] Usage of Dependency Injection with tsrynge
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// example taken from https://blog.logrocket.com/dependency-inversion-principle-typescript | |
// all in one file | |
/** | |
* "reflect-metadata" | |
* This is a [Polyfill](https://developer.mozilla.org/fr/docs/Glossary/Polyfill) allowing | |
* to add the system of [reflection](https://fr.wikipedia.org/wiki/R%C3%A9flexion_(informatique)) | |
* to javascript. | |
* This is a necessary lib for all dependency injection questions (with "tsrynge") | |
* which uses the principle of reflection to operate. | |
* | |
* ```bash | |
* yarn add reflect-metadata | |
* npm install --save reflect-metadata | |
* ``` | |
*/ | |
import 'reflect-metadata'; | |
/** | |
* "tsrynge"'s container | |
* In dependency injection systems, the container is the module that will instantiate each | |
* class and nest them inside each other depending on how it was configured. | |
* This injection is done at runtime. | |
* [Documentation](https://github.com/microsoft/tsyringe#container) | |
* | |
* "injectable" | |
* Indicates to "tsrynge" which class will be injected | |
* | |
* "inject" | |
* Asks to "tsrynge" to inject something into a class | |
* | |
* ```bash | |
* yarn add tsrynge | |
* npm install --save tsrynge | |
* ``` | |
*/ | |
import { container, inject, injectable } from 'tsyringe'; | |
/** | |
* Injection tokens used to configure dependency injection via "tsyringe" | |
*/ | |
const tokens = { | |
PaymentProcessor: Symbol('PaymentProcessor') | |
} as const; | |
// High-level module | |
class ShoppingCartService { | |
constructor( | |
// this decorator will indicate to tsrynge where to inject stuff | |
@inject(tokens.PaymentProcessor) private paymentProcessor: PaymentProcessor, | |
) {} | |
checkout(cart: ShoppingCart) { | |
return this.paymentProcessor.processPayment(cart); | |
} | |
} | |
// Abstraction | |
interface PaymentProcessor { | |
processPayment(cart: ShoppingCart): boolean; | |
} | |
// Implementation of the abstraction | |
@injectable() // this decorator will indicate to tsrynge that this class will be injected | |
class StripePaymentProcessor implements PaymentProcessor { | |
processPayment(cart: ShoppingCart): boolean { | |
// Use the Stripe API to process the payment for the items in the shopping cart | |
} | |
} | |
// Configure injection container to tell him which concrete class will be injected according to which token | |
container.register(tokens.PaymentProcessor, { useClass: StripePaymentProcessor }); | |
// This one-liner is equivalent of | |
const paymentProcessor = new PayPalPaymentProcessor(); | |
const shoppingCartService = new ShoppingCartService(paymentProcessor); | |
// Now the ShoppingCartService depends on the abstraction, not the implementation | |
// following files show how to implement it with good practices |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// at the root of your project | |
import 'reflect-metadata'; | |
import { container } from 'tsyringe'; | |
export default const tokens = { | |
PaymentProcessor: Symbol('PaymentProcessor') | |
} as const; | |
container.register(tokens.PaymentProcessor, { useClass: StripePaymentProcessor }); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export default interface PaymentProcessor { | |
processPayment(cart: ShoppingCart): boolean; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { inject } from 'tsyringe'; | |
import tokens from 'ioc'; | |
import PaymentProcessor from 'payment-processor.interface.ts'; | |
export default class ShoppingCartService { | |
constructor( | |
@inject(tokens.PaymentProcessor) private paymentProcessor: PaymentProcessor, | |
) {} | |
checkout(cart: ShoppingCart) { | |
return this.paymentProcessor.processPayment(cart); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { injectable } from 'tsyringe'; | |
@injectable() | |
export default class StripePaymentProcessor implements PaymentProcessor { | |
processPayment(cart: ShoppingCart): boolean { | |
// Use the Stripe API to process the payment for the items in the shopping cart | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment