### Install TSyringe using npm or yarn Source: https://github.com/microsoft/tsyringe/blob/master/README.md Demonstrates how to add TSyringe to your project dependencies using either npm or yarn package managers. Ensure you have Node.js and npm/yarn installed. ```sh npm install --save tsyringe ``` ```sh yarn add tsyringe ``` -------------------------------- ### Class Provider Registration Example Source: https://github.com/microsoft/tsyringe/blob/master/README.md Shows the structure for registering a class provider with the tsyringe DI container. A class provider consists of a token and the useClass property, which specifies the constructor to be used for resolving instances. ```typescript { token: InjectionToken; useClass: constructor; } ``` -------------------------------- ### Interface Injection Example (TypeScript) Source: https://github.com/microsoft/tsyringe/blob/master/README.md Illustrates how to inject services based on interfaces when runtime type information is not available. This requires explicitly registering the implementation class for the interface token. ```typescript // SuperService.ts export interface SuperService {} // TestService.ts import { SuperService } from "./SuperService"; export class TestService implements SuperService {} // Client.ts import { injectable, inject } from "tsyringe"; import { SuperService } from "./SuperService"; @injectable() export class Client { constructor(@inject("SuperService") private service: SuperService) {} } // main.ts import "reflect-metadata"; import { Client } from "./Client"; import { TestService } from "./TestService"; import { container } from "tsyringe"; container.register("SuperService", { useClass: TestService }); const client = container.resolve(Client); // client's dependencies are resolved ``` -------------------------------- ### Basic Class Injection Example (TypeScript) Source: https://github.com/microsoft/tsyringe/blob/master/README.md A simple example demonstrating dependency injection without interfaces. 'Bar' depends on 'Foo', and tsyringe resolves this dependency by instantiating 'Foo' when 'Bar' is resolved. ```typescript // Foo.ts export class Foo {} // Bar.ts import { Foo } from "./Foo"; import { injectable } from "tsyringe"; @injectable() export class Bar { constructor(public myFoo: Foo) {} } // main.ts import "reflect-metadata"; import { container } from "tsyringe"; import { Bar } from "./Bar"; const myBar = container.resolve(Bar); // myBar.myFoo will be an instance of Foo ``` -------------------------------- ### Basic Dependency Injection with TSyringe Source: https://context7.com/microsoft/tsyringe/llms.txt Demonstrates automatic resolution of class dependencies through constructor injection using the `@injectable()` decorator and the global `container` instance in TSyringe. This example shows how nested dependencies like `UserService` depending on `UserRepository` which depends on `DatabaseService` are automatically managed. ```typescript import "reflect-metadata"; import { injectable, container } from "tsyringe"; // Define injectable services @injectable() class DatabaseService { query(sql: string): any[] { console.log(`Executing: ${sql}`); return [{ id: 1, name: "John" }]; } } @injectable() class UserRepository { constructor(private db: DatabaseService) {} findById(id: number) { return this.db.query(`SELECT * FROM users WHERE id = ${id}`); } } @injectable() class UserService { constructor(private repo: UserRepository) {} getUser(id: number) { return this.repo.findById(id); } } // Resolve with automatic dependency injection const userService = container.resolve(UserService); const user = userService.getUser(1); console.log(user); // [{ id: 1, name: "John" }] ``` -------------------------------- ### Value Provider Example in TypeScript Source: https://github.com/microsoft/tsyringe/blob/master/README.md The Value provider registers a constant or pre-instantiated object for a given token. It directly maps an InjectionToken to a specific value, useful for configuration constants or singleton objects. ```TypeScript { token: InjectionToken; useValue: T } ``` -------------------------------- ### Factory Provider Example in TypeScript Source: https://github.com/microsoft/tsyringe/blob/master/README.md The Factory provider uses a factory function to resolve a token. The factory function receives the dependency container, allowing it to resolve other dependencies to construct the required object. This enables dynamic object creation and complex initialization logic. ```TypeScript { token: InjectionToken; useFactory: FactoryFunction; } ``` -------------------------------- ### Circular Dependencies Example (TypeScript) Source: https://github.com/microsoft/tsyringe/blob/master/README.md Demonstrates a scenario with circular dependencies between two services, 'Foo' and 'Bar', which would normally cause an error during resolution. This highlights the problem that the `delay` function aims to solve. ```typescript import { injectable } from "tsyringe"; @injectable() export class Foo { constructor(public bar: Bar) {} } @injectable() export class Bar { constructor(public foo: Foo) {} } ``` -------------------------------- ### Interfaces and Circular Dependencies with delay() (TypeScript) Source: https://github.com/microsoft/tsyringe/blob/master/README.md Illustrates the use of `delay` with interfaces to manage circular dependencies. This example shows how to register delayed constructors for interfaces, enabling tsyringe to resolve dependencies between services that rely on interface tokens. ```typescript import { injectable, inject, delay, registry } from "tsyringe"; export interface IFoo {} export interface IBar {} @injectable() @registry([ { token: "IBar", useToken: delay(() => Bar) } ]) export class Foo implements IFoo { constructor(@inject("IBar") public bar: IBar) {} } @injectable() @registry([ { token: "IFoo", useToken: delay(() => Foo) } ]) export class Bar implements IBar { constructor(@inject("IFoo") public foo: IFoo) {} } ``` -------------------------------- ### Registry Decorator - Bulk Register Dependencies Source: https://context7.com/microsoft/tsyringe/llms.txt The @registry decorator simplifies the process of registering multiple dependencies at once. It accepts an array of registration objects, allowing for cleaner configuration management. This pattern is particularly useful for grouping related services like repositories or loggers. The example shows how to register multiple repositories and multiple logger implementations. ```typescript import { injectable, registry, container } from "tsyringe"; // Repository implementations class UserRepository { findAll(): string[] { return ["user1", "user2"]; } } class OrderRepository { findAll(): string[] { return ["order1", "order2"]; } } class ProductRepository { findAll(): string[] { return ["product1", "product2"]; } } // Logger implementations class ConsoleLogger { log(msg: string): void { console.log(`[CONSOLE] ${msg}`); } } class FileLogger { log(msg: string): void { console.log(`[FILE] ${msg}`); } } // Register all repositories in one place @registry([ { token: "UserRepository", useClass: UserRepository }, { token: "OrderRepository", useClass: OrderRepository }, { token: "ProductRepository", useClass: ProductRepository } ]) class RepositoryRegistry {} // Register all loggers @registry([ { token: "Logger", useFactory: (c) => new ConsoleLogger() }, { token: "Logger", useFactory: (c) => new FileLogger() } ]) class LoggerRegistry {} // Import registries to activate import {} from "./RepositoryRegistry"; import {} from "./LoggerRegistry"; // Now resolve const userRepo = container.resolve("UserRepository"); const loggers = container.resolveAll("Logger"); console.log(userRepo.findAll()); // ["user1", "user2"] loggers.forEach(logger => logger.log("Application started")); // Output: // ["user1", "user2"] // [CONSOLE] Application started // [FILE] Application started ``` -------------------------------- ### Token Provider Example in TypeScript Source: https://github.com/microsoft/tsyringe/blob/master/README.md The Token provider acts as an alias or redirect, mapping one InjectionToken to another. When a token is requested, the provider resolves the value associated with the aliased token. This is useful for simplifying token management or refactoring. ```TypeScript { token: InjectionToken; useToken: InjectionToken; } ``` -------------------------------- ### Transform Decorators - Transform Dependencies Before Injection Source: https://context7.com/microsoft/tsyringe/llms.txt The @injectWithTransform and @injectAllWithTransform decorators allow you to apply transformations to resolved dependencies before they are injected. This is useful for extracting specific values or transforming collections of objects. Transformers must implement the `Transform` interface and can be registered with the container. The example demonstrates transforming feature flags and plugin versions. ```typescript import { injectable, inject, injectWithTransform, injectAllWithTransform, container } from "tsyringe"; import { Transform } from "tsyringe"; @injectable() class FeatureFlags { private flags = { enableNewUI: true, enableBetaFeatures: false, enableExperimentalAPI: true }; getFlagValue(flagName: string): boolean { return this.flags[flagName] || false; } } // Transformer to extract single flag value class FeatureFlagTransformer implements Transform { transform(flags: FeatureFlags, flagName: string): boolean { return flags.getFlagValue(flagName); } } @injectable() class Plugin { constructor(public name: string) {} getVersion(): string { return "1.0.0"; } } // Transformer to extract versions from plugins class PluginVersionTransformer implements Transform { transform(plugins: Plugin[]): string[] { return plugins.map(p => `${p.name}:${p.getVersion()}`); } } // Register transformers and plugins container.register(FeatureFlagTransformer, { useClass: FeatureFlagTransformer }); container.register(PluginVersionTransformer, { useClass: PluginVersionTransformer }); container.register("Plugin", { useClass: Plugin }); @injectable() class Application { constructor( @injectWithTransform( FeatureFlags, FeatureFlagTransformer, "enableNewUI" ) private newUIEnabled: boolean, @injectWithTransform( FeatureFlags, FeatureFlagTransformer, "enableBetaFeatures" ) private betaEnabled: boolean, @injectAllWithTransform( "Plugin", PluginVersionTransformer ) private pluginVersions: string[] ) {} start(): void { console.log(`New UI: ${this.newUIEnabled}`); console.log(`Beta Features: ${this.betaEnabled}`); console.log(`Plugins: ${this.pluginVersions.join(", ")}`); } } const app = container.resolve(Application); app.start(); // Output: // New UI: true // Beta Features: false // Plugins: undefined:1.0.0 ``` -------------------------------- ### Token Aliasing and Redirection with tsyringe Source: https://context7.com/microsoft/tsyringe/llms.txt Demonstrates how to create aliases and redirections between tokens for flexible dependency resolution and interface-to-implementation mapping in tsyringe. This allows for dynamic switching of implementations based on environment variables or other conditions. ```typescript import { injectable, container } from "tsyringe"; @injectable() class ProductionDatabase { query(): string { return "Production data"; } } @injectable() class DevelopmentDatabase { query(): string { return "Development data"; } } // Register implementations container.register("ProductionDatabase", { useClass: ProductionDatabase }); container.register("DevelopmentDatabase", { useClass: DevelopmentDatabase }); // Create alias based on environment const isDevelopment = process.env.NODE_ENV !== "production"; container.register("Database", { useToken: isDevelopment ? "DevelopmentDatabase" : "ProductionDatabase" }); // Another alias container.register("PrimaryDatabase", { useToken: "Database" }); @injectable() class DataService { constructor(private db: ProductionDatabase | DevelopmentDatabase) {} getData(): string { return this.db.query(); } } // Resolve through alias chain: PrimaryDatabase -> Database -> DevelopmentDatabase const db = container.resolve("PrimaryDatabase"); console.log(db.query()); // "Development data" ``` -------------------------------- ### Factory Provider for Dynamic Instantiation - Tsyringe Source: https://context7.com/microsoft/tsyringe/llms.txt This snippet illustrates using a factory provider in tsyringe for dynamic instantiation. Factory functions are beneficial for complex initialization logic, conditional instantiation, and runtime configuration of dependencies. ```typescript import { container, injectable } from "tsyringe"; interface DatabaseConfig { host: string; port: number; ssl: boolean; } class DatabaseConnection { constructor(private config: DatabaseConfig) {} connect(): void { const protocol = this.config.ssl ? "https" : "http"; console.log(`Connecting to ${protocol}://${this.config.host}:${this.config.port}`); } } @injectable() class EnvironmentConfig { getDbConfig(): DatabaseConfig { return { host: process.env.DB_HOST || "localhost", port: parseInt(process.env.DB_PORT || "5432"), ssl: process.env.DB_SSL === "true" }; } } // Register with factory container.register("DatabaseConnection", { useFactory: (container) => { const envConfig = container.resolve(EnvironmentConfig); const dbConfig = envConfig.getDbConfig(); return new DatabaseConnection(dbConfig); } }); const db = container.resolve("DatabaseConnection"); db.connect(); // Connecting to http://localhost:5432 ``` -------------------------------- ### Resolve All Instances with tsyringe Source: https://github.com/microsoft/tsyringe/blob/master/README.md Shows how to resolve all instances registered against a specific token using `resolveAll()`. This is useful when multiple providers are registered for the same token. ```typescript interface Bar {} @injectable() class Foo implements Bar {} @injectable() class Baz implements Bar {} @registry([ {token: "Bar", useToken: Foo}, {token: "Bar", useToken: Baz} ]) class MyRegistry {} const myBars = container.resolveAll("Bar"); // myBars type is Bar[] ``` -------------------------------- ### Basic Registration with DependencyContainer in TypeScript Source: https://github.com/microsoft/tsyringe/blob/master/README.md Demonstrates the fundamental usage of DependencyContainer.register() to register different types of providers. It shows registering a class, a pre-instantiated value, and a value with a string token. ```TypeScript container.register(Foo, {useClass: Foo}); container.register(Bar, {useValue: new Bar()}); container.register("MyBaz", {useValue: new Baz()}); ``` -------------------------------- ### Configure tsconfig.json for TSyringe Source: https://github.com/microsoft/tsyringe/blob/master/README.md Explains the necessary TypeScript compiler options to enable decorators and metadata emission, which are crucial for TSyringe's functionality. Apply these settings in your tsconfig.json file. ```json { "compilerOptions": { "experimentalDecorators": true, "emitDecoratorMetadata": true } } ``` -------------------------------- ### Singleton Registration with TSyringe for Shared Instances Source: https://context7.com/microsoft/tsyringe/llms.txt Illustrates how to register classes as singletons using the `@singleton()` decorator in TSyringe. This ensures that only one instance of the registered class is created and shared across all resolutions throughout the application's lifecycle, as shown with `ConfigurationService` and `Logger`. ```typescript import { singleton, container } from "tsyringe"; @singleton() class ConfigurationService { private config = { apiUrl: "https://api.example.com", timeout: 5000 }; get(key: string): any { return this.config[key]; } } @singleton() class Logger { private logs: string[] = []; log(message: string): void { this.logs.push(`${new Date().toISOString()}: ${message}`); } getLogs(): string[] { return [...this.logs]; } } // Both resolves return the same instance const logger1 = container.resolve(Logger); const logger2 = container.resolve(Logger); logger1.log("First message"); logger2.log("Second message"); console.log(logger1 === logger2); // true console.log(logger1.getLogs()); // ["2025-10-28...: First message", "2025-10-28...: Second message"] ``` -------------------------------- ### TypeScript: Intercepting Service Resolutions with Lifecycle Hooks Source: https://context7.com/microsoft/tsyringe/llms.txt Shows how to use tsyringe's `beforeResolution` and `afterResolution` hooks to intercept the instantiation process of services. These hooks are useful for implementing initialization logic, logging, monitoring, and aspect-oriented programming before and after a service is resolved. ```typescript import { injectable, container } from "tsyringe"; @injectable() class ExpensiveService { private initialized = false; init(): void { console.log("Initializing expensive service..."); this.initialized = true; } doWork(): string { if (!this.initialized) throw new Error("Not initialized"); return "Work completed"; } } @injectable() class TrackedService { execute(): void { console.log("Executing tracked operation"); } } // Pre-resolution hook - runs before resolution container.beforeResolution( ExpensiveService, (token, resolutionType) => { console.log(`About to resolve ${token.name} (${resolutionType})`); }, { frequency: "Always" } ); // Post-resolution hook - runs after resolution container.afterResolution( ExpensiveService, (token, result) => { console.log("Initializing service post-resolution"); result.init(); }, { frequency: "Once" } // Only initialize once ); // Logging interceptor for all resolutions container.beforeResolution( TrackedService, () => console.log(`[${new Date().toISOString()}] Resolving TrackedService`), { frequency: "Always" } ); // Resolve services const expensive1 = container.resolve(ExpensiveService); const expensive2 = container.resolve(ExpensiveService); console.log(expensive1.doWork()); // "Work completed" console.log(expensive2.doWork()); // "Work completed" const tracked = container.resolve(TrackedService); tracked.execute(); ``` -------------------------------- ### Creating Child Containers in tsyringe Source: https://github.com/microsoft/tsyringe/blob/master/README.md Demonstrates the creation of independent child containers using `createChildContainer()`. Child containers inherit registrations from their parent if a token is not found locally. ```typescript const childContainer1 = container.createChildContainer(); const childContainer2 = container.createChildContainer(); const grandChildContainer = childContainer1.createChildContainer(); ``` -------------------------------- ### Inject Multiple Implementations with @injectAll() - Tsyringe Plugin System Source: https://context7.com/microsoft/tsyringe/llms.txt This snippet demonstrates how to register and inject multiple implementations for the same token using `@injectAll()` in tsyringe. This pattern is useful for building plugin architectures and strategy patterns where different implementations of an interface need to be available. ```typescript import { injectable, injectAll, container } from "tsyringe"; interface IPaymentProcessor { processPayment(amount: number): boolean; } @injectable() class StripeProcessor implements IPaymentProcessor { processPayment(amount: number): boolean { console.log(`Processing $${amount} via Stripe`); return true; } } @injectable() class PayPalProcessor implements IPaymentProcessor { processPayment(amount: number): boolean { console.log(`Processing $${amount} via PayPal`); return true; } } @injectable() class CryptoProcessor implements IPaymentProcessor { processPayment(amount: number): boolean { console.log(`Processing $${amount} via Cryptocurrency`); return true; } } // Register multiple implementations container.register("IPaymentProcessor", { useClass: StripeProcessor }); container.register("IPaymentProcessor", { useClass: PayPalProcessor }); container.register("IPaymentProcessor", { useClass: CryptoProcessor }); @injectable() class PaymentGateway { constructor( @injectAll("IPaymentProcessor") private processors: IPaymentProcessor[] ) {} processWithAllMethods(amount: number): void { console.log(`Processing payment with ${this.processors.length} methods`); this.processors.forEach(processor => processor.processPayment(amount)); } } const gateway = container.resolve(PaymentGateway); gateway.processWithAllMethods(100); // Output: // Processing payment with 3 methods // Processing $100 via Stripe // Processing $100 via PayPal // Processing $100 via Cryptocurrency ``` -------------------------------- ### TypeScript: Optional Dependency Injection with AutoInjectable Source: https://context7.com/microsoft/tsyringe/llms.txt Demonstrates how to use the `@autoInjectable()` decorator in tsyringe to allow classes to be instantiated with the `new` keyword while still supporting automatic dependency injection for optional dependencies. Dependencies are injected if provided, otherwise they remain undefined. ```typescript import { autoInjectable, singleton, injectable } from "tsyringe"; @singleton() class Logger { log(msg: string): void { console.log(`[LOG] ${msg}`); } } @injectable() class MetricsCollector { track(event: string): void { console.log(`[METRIC] ${event}`); } } @autoInjectable() class FeatureService { constructor( private logger?: Logger, private metrics?: MetricsCollector ) {} executeFeature(name: string): void { this.logger?.log(`Executing feature: ${name}`); this.metrics?.track(`feature_executed:${name}`); console.log(`Feature ${name} completed`); } } // Can instantiate with new - dependencies auto-injected const service1 = new FeatureService(); service1.executeFeature("auto-save"); // Or manually provide dependencies const customLogger = new Logger(); const service2 = new FeatureService(customLogger); service2.executeFeature("export"); ``` -------------------------------- ### Basic Dependency Injection with @inject() in TypeScript Source: https://github.com/microsoft/tsyringe/blob/master/README.md Demonstrates how to use the @injectable() and @inject() decorators to inject dependencies into a class constructor. The @inject() decorator specifies the token for the dependency, which in this case is a string 'Database'. If the dependency is not found, it will throw an exception by default. ```typescript import {injectable, inject} from "tsyringe"; interface Database { // ... } @injectable() class Foo { constructor(@inject("Database") private database?: Database) {} } ``` -------------------------------- ### Resolve Single Instance with tsyringe Source: https://github.com/microsoft/tsyringe/blob/master/README.md Demonstrates resolving a single instance of a token from the container using the `resolve()` method. This is the primary way to obtain an object managed by tsyringe. ```typescript const myFoo = container.resolve(Foo); const myBar = container.resolve("Bar"); ``` -------------------------------- ### Lifecycle Scopes Management with tsyringe Source: https://context7.com/microsoft/tsyringe/llms.txt Explains and demonstrates the four lifecycle scope types in tsyringe: Transient, Singleton, ResolutionScoped, and ContainerScoped. This controls how instances are created and reused within the dependency injection container. ```typescript import { injectable, container, Lifecycle, scoped } from "tsyringe"; // Transient: new instance every time @injectable() class TransientService { id = Math.random(); } // Singleton: one instance globally @scoped(Lifecycle.Singleton) class SingletonService { id = Math.random(); } // ResolutionScoped: same instance within one resolution chain container.register("RequestContext", { useClass: class RequestContext { id = Math.random(); } }, { lifecycle: Lifecycle.ResolutionScoped } ); // ContainerScoped: one instance per container @scoped(Lifecycle.ContainerScoped) class ContainerScopedCache { data = new Map(); } @injectable() class ServiceA { constructor( public transient: TransientService, public singleton: SingletonService, @inject("RequestContext") public context: any ) {} } @injectable() class ServiceB { constructor( public transient: TransientService, public singleton: SingletonService, @inject("RequestContext") public context: any ) {} } const a1 = container.resolve(ServiceA); const a2 = container.resolve(ServiceA); console.log(a1.transient.id !== a2.transient.id); // true - different instances console.log(a1.singleton.id === a2.singleton.id); // true - same instance console.log(a1.context.id !== a2.context.id); // true - different resolution chains // Within same resolution chain @injectable() class Parent { constructor(public a: ServiceA, public b: ServiceB) {} } const parent = container.resolve(Parent); console.log(parent.a.context.id === parent.b.context.id); // true - same resolution console.log(parent.a.singleton.id === parent.b.singleton.id); // true - singleton ``` -------------------------------- ### Value Provider for Constants and Primitives - Tsyringe Source: https://context7.com/microsoft/tsyringe/llms.txt This snippet demonstrates using the value provider in tsyringe to register and inject primitive values, configuration objects, and pre-instantiated objects. This is useful for injecting constants, feature flags, or shared instances. ```typescript import { injectable, inject, container } from "tsyringe"; // Register primitive values container.register("API_KEY", { useValue: "sk_live_abc123xyz" }); container.register("API_TIMEOUT", { useValue: 30000 }); container.register("FEATURE_FLAGS", { useValue: { enableNewUI: true, enableBetaFeatures: false } }); // Register pre-instantiated object const sharedCache = new Map(); container.register("CacheInstance", { useValue: sharedCache }); @injectable() class ApiClient { constructor( @inject("API_KEY") private apiKey: string, @inject("API_TIMEOUT") private timeout: number, @inject("CacheInstance") private cache: Map ) {} async fetchData(endpoint: string): Promise { const cached = this.cache.get(endpoint); if (cached) return cached; console.log(`Fetching ${endpoint} with key ${this.apiKey.substring(0, 10)}...`); console.log(`Timeout: ${this.timeout}ms`); const data = { result: "data" }; this.cache.set(endpoint, data); return data; } } const client = container.resolve(ApiClient); client.fetchData("/users"); // Output: Fetching /users with key sk_live_ab... // Timeout: 30000ms ``` -------------------------------- ### Add Reflect API Polyfill Source: https://github.com/microsoft/tsyringe/blob/master/README.md Shows how to import a Reflect API polyfill, such as reflect-metadata, in your main application file. This import must occur before any TSyringe DI is used and is essential for decorator metadata handling. ```typescript // main.ts import "reflect-metadata"; // Your code here... ``` -------------------------------- ### Configure Babel for TypeScript Metadata Source: https://github.com/microsoft/tsyringe/blob/master/README.md Provides instructions for integrating the babel-plugin-transform-typescript-metadata with Babel, commonly used in environments like React Native. This ensures TypeScript metadata is correctly emitted when using Babel. ```sh yarn add --dev babel-plugin-transform-typescript-metadata ``` ```sh npm install --save-dev babel-plugin-transform-typescript-metadata ``` ```javascript plugins: [ 'babel-plugin-transform-typescript-metadata', /* ...the rest of your config... */ ] ``` -------------------------------- ### Before Resolution Interception with tsyringe Source: https://github.com/microsoft/tsyringe/blob/master/README.md Shows how to register a callback to execute before an object is resolved using `beforeResolution()`. This callback can be configured to run always or once. ```typescript class Bar {} container.beforeResolution( Bar, // Callback signature is (token: InjectionToken, resolutionType: ResolutionType) => void () => { console.log("Bar is about to be resolved!"); }, {frequency: "Always"} ); ``` -------------------------------- ### Use @injectable Decorator with TSyringe Source: https://github.com/microsoft/tsyringe/blob/master/README.md Demonstrates the usage of the `@injectable()` decorator, a class decorator factory that marks a class as eligible for dependency injection. It shows how to import and apply the decorator and how to resolve an instance from the container. ```typescript import {injectable} from "tsyringe"; @injectable() class Foo { constructor(private database: Database) {} } // some other file import "reflect-metadata"; import {container} from "tsyringe"; import {Foo} from "./foo"; const instance = container.resolve(Foo); ``` -------------------------------- ### TypeScript: Automatic Resource Cleanup with Disposable Interface Source: https://context7.com/microsoft/tsyringe/llms.txt Demonstrates how to implement the Disposable interface in tsyringe to ensure automatic cleanup of resources when the container is disposed. This pattern is useful for managing connections or streams that require explicit closing. It relies on the Disposable and injectable decorators from 'tsyringe'. ```typescript import { injectable, container, Disposable } from "tsyringe"; @injectable() class DatabaseConnection implements Disposable { private connected = true; constructor() { console.log("Database connection established"); } query(sql: string): any { if (!this.connected) throw new Error("Connection closed"); return { result: "data" }; } async dispose(): Promise { console.log("Closing database connection..."); this.connected = false; // Simulate async cleanup await new Promise(resolve => setTimeout(resolve, 100)); console.log("Database connection closed"); } } @injectable() class FileStream implements Disposable { constructor() { console.log("File stream opened"); } write(data: string): void { console.log(`Writing: ${data}`); } dispose(): void { console.log("File stream closed"); } } @injectable() class Application { constructor( private db: DatabaseConnection, private file: FileStream ) {} run(): void { const data = this.db.query("SELECT * FROM users"); this.file.write(JSON.stringify(data)); } } async function main() { const app = container.resolve(Application); app.run(); // Cleanup all disposable resources await container.dispose(); } main(); ``` -------------------------------- ### Class Registration with @registry() Decorator in TypeScript Source: https://github.com/microsoft/tsyringe/blob/master/README.md Illustrates using the @registry() decorator on a class to automatically register providers upon import. This method is an alternative to manual container registration and is useful for organizing providers or registering third-party instances. ```TypeScript @registry([ { token: Foobar, useClass: Foobar }, { token: "theirClass", useFactory: (c) => { return new TheirClass( "arg" ) }, } ]) class MyClass {} ``` -------------------------------- ### Registering Tokens with @injectable Decorator in tsyringe Source: https://github.com/microsoft/tsyringe/blob/master/README.md Illustrates how to directly add one or more `InjectionToken` to a class registration using the `@injectable()` decorator. This simplifies registration for classes that should be known by multiple tokens. ```typescript interface Bar {} @injectable({token: "Bar"}) class Foo implements Bar {} @injectable({token: ["Bar", "Bar2"]}) class Baz implements Bar {} class MyRegistry {} const myBars = container.resolveAll("Bar"); // myBars type is Bar[], contains 2 instances const myBars2 = container.resolveAll("Bar2"); // myBars2 type is Bar[], contains 1 instance ``` -------------------------------- ### Injecting Arrays with @injectAll() in TypeScript Source: https://github.com/microsoft/tsyringe/blob/master/README.md Illustrates using the @injectAll() decorator to inject an array of dependencies resolved from the container using a specified injection token. By default, if no registrations are found, it throws an exception. ```typescript import {injectable, injectAll} from "tsyringe"; @injectable() class Foo {} @injectable() class Bar { constructor(@injectAll(Foo) fooArray: Foo[]) { // ... } } ``` -------------------------------- ### Interface Injection with Named Tokens in TSyringe Source: https://context7.com/microsoft/tsyringe/llms.txt Shows how to perform interface injection using named tokens (strings or symbols) with the `@inject()` decorator in TSyringe. This pattern is useful for decoupling concrete implementations from the interfaces they implement, allowing for easier swapping of implementations, as demonstrated with `IEmailService` and its providers. ```typescript import { injectable, inject, container } from "tsyringe"; // Define interface interface IEmailService { send(to: string, subject: string, body: string): void; } // Implement interface class SendGridEmailService implements IEmailService { send(to: string, subject: string, body: string): void { console.log(`Sending via SendGrid to ${to}: ${subject}`); } } class MailgunEmailService implements IEmailService { send(to: string, subject: string, body: string): void { console.log(`Sending via Mailgun to ${to}: ${subject}`); } } // Register implementation container.register("IEmailService", { useClass: SendGridEmailService }); // Inject using token @injectable() class NotificationService { constructor( @inject("IEmailService") private emailService: IEmailService ) {} notifyUser(email: string, message: string): void { this.emailService.send(email, "Notification", message); } } const notifier = container.resolve(NotificationService); notifier.notifyUser("user@example.com", "Welcome!"); // Output: Sending via SendGrid to user@example.com: Notification ``` -------------------------------- ### Disposing Instances (TypeScript) Source: https://github.com/microsoft/tsyringe/blob/master/README.md Demonstrates how to dispose of instances managed by the tsyringe container. If an instance implements the `Disposable` interface, it will be automatically disposed of when the container is disposed. This can be done synchronously or asynchronously. ```typescript // Synchronous disposal container.dispose(); // Asynchronous disposal (awaits all async disposals) await container.dispose(); ``` -------------------------------- ### TypeScript: Instance Management for Testing and Lifecycle Control Source: https://context7.com/microsoft/tsyringe/llms.txt Illustrates how to manage container instances in tsyringe for testing and lifecycle control. It shows the use of `clearInstances()` to isolate tests by removing cached instances while retaining registrations, and `reset()` to completely clear both instances and registrations. This is crucial for ensuring predictable test outcomes. ```typescript import { singleton, injectable, container } from "tsyringe"; @singleton() class UserCache { private users = new Map(); set(id: string, user: any): void { this.users.set(id, user); } get(id: string): any { return this.users.get(id); } size(): number { return this.users.size; } } @injectable() class SessionManager { sessionId = Math.random().toString(36); } // Test scenario 1 const cache1 = container.resolve(UserCache); cache1.set("user-1", { name: "Alice" }); console.log(cache1.size()); // 1 const session1 = container.resolve(SessionManager); console.log(session1.sessionId); // e.g., "abc123" // Clear instances but keep registrations container.clearInstances(); // Test scenario 2 - fresh instances const cache2 = container.resolve(UserCache); console.log(cache2.size()); // 0 - new instance console.log(cache1 === cache2); // false - different instances const session2 = container.resolve(SessionManager); console.log(session2.sessionId !== session1.sessionId); // true - new instance // Verify singleton behavior still works after clear const cache3 = container.resolve(UserCache); console.log(cache2 === cache3); // true - same singleton after clear // Complete reset - clears registrations too container.reset(); try { container.resolve(UserCache); // Throws error - registration cleared } catch (e) { console.log("Registration cleared after reset"); } ``` -------------------------------- ### Use @singleton Decorator with TSyringe Source: https://github.com/microsoft/tsyringe/blob/master/README.md Illustrates the application of the `@singleton()` decorator, which registers a class as a singleton in the global container. This ensures that only one instance of the decorated class is ever created and reused across the application. ```typescript import {singleton} from "tsyringe"; @singleton() class Foo { constructor() {} } // some other file import "reflect-metadata"; import {container} from "tsyringe"; import {Foo} from "./foo"; const instance = container.resolve(Foo); ``` -------------------------------- ### After Resolution Interception with tsyringe Source: https://github.com/microsoft/tsyringe/blob/master/README.md Illustrates registering a callback to execute after an object has been resolved using `afterResolution()`. This is useful for post-resolution logic like initialization or logging. ```typescript class Bar { public init(): void { // ... } } container.afterResolution( Bar, // Callback signature is (token: InjectionToken, result: T | T[], resolutionType: ResolutionType) (_t, result) => { result.init(); }, {frequency: "Once"} ); ``` -------------------------------- ### Named Injection of Primitive Values (TypeScript) Source: https://github.com/microsoft/tsyringe/blob/master/README.md Demonstrates how to inject primitive values like strings using named injection. A specific string value is registered with a token and then injected into a class constructor using the `@inject` decorator. ```typescript // Foo.ts import { singleton, inject } from "tsyringe"; @singleton() class Foo { private str: string; constructor(@inject("SpecialString") value: string) { this.str = value; } } // some other file import "reflect-metadata"; import { container } from "tsyringe"; import { Foo } from "./Foo"; const str = "test"; container.register("SpecialString", {useValue: str}); const instance = container.resolve(Foo); ``` -------------------------------- ### Resolving Circular Dependencies with delay() (TypeScript) Source: https://github.com/microsoft/tsyringe/blob/master/README.md Shows how to use the `delay` helper function to overcome circular dependencies. By wrapping the dependency injection with `delay`, tsyringe creates a proxy that defers the actual instantiation until it's first used, thus breaking the cycle. ```typescript import { injectable, inject, delay } from "tsyringe"; export interface IBar {} export interface IFoo {} @injectable() export class Foo implements IFoo { constructor(@inject(delay(() => Bar)) public bar: IBar) {} } @injectable() export class Bar implements IBar { constructor(@inject(delay(() => Foo)) public foo: IFoo) {} } // Example usage: // const foo = container.resolve(Foo); // foo.bar instanceof Bar; // true ``` -------------------------------- ### Child Containers for Hierarchical Scoping in tsyringe Source: https://context7.com/microsoft/tsyringe/llms.txt Illustrates how to create child containers in tsyringe, enabling isolated scopes that inherit parent registrations. This pattern is useful for managing request-specific dependencies while sharing global resources. ```typescript import { injectable, container, Lifecycle } from "tsyringe"; // Global services @injectable() class DatabasePool { connections = 10; } @injectable() class CacheService { store = new Map(); } // Request-scoped service class RequestContext { requestId = Math.random().toString(36).substring(7); userId?: string; } // Register request-scoped container.register(RequestContext, { useClass: RequestContext }, { lifecycle: Lifecycle.ContainerScoped } ); @injectable() class RequestHandler { constructor( private db: DatabasePool, private cache: CacheService, private context: RequestContext ) {} handle(userId: string): void { this.context.userId = userId; console.log(`Request ${this.context.requestId} for user ${userId}`); console.log(`Using DB pool with ${this.db.connections} connections`); } } // Simulate two concurrent requests const request1Container = container.createChildContainer(); const request2Container = container.createChildContainer(); const handler1 = request1Container.resolve(RequestHandler); const handler2 = request2Container.resolve(RequestHandler); handler1.handle("user-123"); handler2.handle("user-456"); // Each has unique context but shares DB pool console.log(handler1["context"].requestId !== handler2["context"].requestId); // true console.log(handler1["db"] === handler2["db"]); // true - shared from parent ``` -------------------------------- ### TypeScript: Resolving Circular Dependencies with Delay Source: https://context7.com/microsoft/tsyringe/llms.txt Illustrates how to resolve circular dependencies between services in tsyringe using the `delay()` helper function. This pattern enables lazy instantiation of dependent services, preventing initialization errors when services depend on each other. ```typescript import { injectable, inject, delay, container } from "tsyringe"; @injectable() class UserService { constructor( @inject(delay(() => OrderService)) public orderService: OrderService ) {} getUserOrders(userId: string): string[] { console.log("UserService: Getting orders for user"); return this.orderService.getOrdersByUser(userId); } } @injectable() class OrderService { constructor( @inject(delay(() => UserService)) public userService: UserService ) {} getOrdersByUser(userId: string): string[] { console.log("OrderService: Fetching orders"); return ["order-1", "order-2"]; } notifyUser(orderId: string, userId: string): void { const orders = this.userService.getUserOrders(userId); console.log(`User has ${orders.length} orders`); } } // Resolution succeeds despite circular dependency const userService = container.resolve(UserService); const orders = userService.getUserOrders("user-123"); console.log(userService.orderService instanceof OrderService); // true console.log(orders); // ["order-1", "order-2"] ``` -------------------------------- ### Use @autoInjectable Decorator with TSyringe Source: https://github.com/microsoft/tsyringe/blob/master/README.md Shows how to use the `@autoInjectable()` decorator to automatically resolve dependencies for a class. This decorator replaces the constructor with a parameterless one, simplifying instantiation, but requires parameters to be optional. ```typescript import {autoInjectable} from "tsyringe"; @autoInjectable() class Foo { constructor(private database?: Database) {} } // some other file import {Foo} from "./foo"; const instance = new Foo(); ``` -------------------------------- ### Clearing Instances with tsyringe clearInstances Source: https://github.com/microsoft/tsyringe/blob/master/README.md Explains how to clear all previously created and registered instances using `clearInstances()`. This method does not clear registrations but resets singleton scopes and instance registrations. ```typescript class Foo {} @singleton() class Bar {} const myFoo = new Foo(); container.registerInstance("Test", myFoo); const myBar = container.resolve(Bar); container.clearInstances(); container.resolve("Test"); // throws error const myBar2 = container.resolve(Bar); // myBar !== myBar2 const myBar3 = container.resolve(Bar); // myBar2 === myBar3 ``` ```typescript @singleton() class Foo {} beforeEach(() => { container.clearInstances(); }); test("something", () => { container.resolve(Foo); // will be a new singleton instance in every test }); ``` -------------------------------- ### Check Token Registration with tsyringe isRegistered Source: https://github.com/microsoft/tsyringe/blob/master/README.md Demonstrates checking if a token is currently registered within the container using the `isRegistered()` method. It can also recursively check parent containers. ```typescript const isRegistered = container.isRegistered("Bar"); // true ``` ```typescript class Bar {} container.register(Bar, {useClass: Bar}); const childContainer = container.createChildContainer(); childContainer.isRegistered(Bar); // false childContainer.isRegistered(Bar, true); // true ``` -------------------------------- ### Optional Array Injection with @injectAll(..., { isOptional: true }) in TypeScript Source: https://github.com/microsoft/tsyringe/blob/master/README.md Demonstrates how to make array dependency injection optional with the { isOptional: true } option for @injectAll(). If no registrations are found for the token, an empty array will be injected instead of throwing an error. ```typescript import {injectable, injectAll} from "tsyringe"; @injectable() class Foo {} @injectable() class Bar { constructor(@injectAll(Foo, { isOptional: true }) fooArray: Foo[]) { // ... } } ``` -------------------------------- ### Instance Caching Factory in TypeScript Source: https://github.com/microsoft/tsyringe/blob/master/README.md The instanceCachingFactory creates a singleton instance of an object. It lazily constructs the object on the first resolution and caches the result, returning the same instance for all subsequent requests. This is equivalent to the @singleton() decorator. ```TypeScript import {instanceCachingFactory} from "tsyringe"; { token: "SingletonFoo"; useFactory: instanceCachingFactory(c => c.resolve(Foo)); } ``` -------------------------------- ### Scoped Registration with @scoped() in TypeScript Source: https://github.com/microsoft/tsyringe/blob/master/README.md Demonstrates using the @scoped() class decorator factory to register a class with a specific lifecycle scope within the container. Available scopes include Transient, Singleton, ResolutionScoped, and ContainerScoped, each defining how instances are managed and reused. ```typescript @scoped(Lifecycle.ContainerScoped) class Foo {} ``` -------------------------------- ### Optional Dependency Injection with @inject(..., { isOptional: true }) in TypeScript Source: https://github.com/microsoft/tsyringe/blob/master/README.md Shows how to make a dependency injection optional using the { isOptional: true } option with the @inject() decorator. If the dependency registration is not found, `undefined` will be injected instead of throwing an error. ```typescript import {injectable, inject} from "tsyringe"; @injectable() class Foo { constructor(@inject("Database", { isOptional: true }) private database?: Database) {} } ``` -------------------------------- ### Transforming Injected Values with @injectWithTransform() in TypeScript Source: https://github.com/microsoft/tsyringe/blob/master/README.md Shows how to use @injectWithTransform() to apply a transformation to a resolved dependency before it's injected. The decorator takes the injection token, a transformer class implementing the Transform interface, and an optional name for the transformation. ```typescript class FeatureFlags { public getFlagValue(flagName: string): boolean { // ... } } class Foo {} class FeatureFlagsTransformer implements Transform { public transform(flags: FeatureFlags, flag: string) { return flags.getFlagValue(flag); } } @injectable() class MyComponent(foo: Foo, @injectWithTransform(FeatureFlags, FeatureFlagsTransformer, "IsBlahEnabled") blahEnabled: boolean){ // ... } ``` -------------------------------- ### Instance Per Container Caching Factory in TypeScript Source: https://github.com/microsoft/tsyringe/blob/master/README.md The instancePerContainerCachingFactory creates an object instance that is cached per dependency container. Each container will have its own unique instance of the object, providing scoped instances similar to @scoped(Lifecycle.ContainerScoped). ```TypeScript import {instancePerContainerCachingFactory} from "tsyringe"; { token: "ContainerScopedFoo"; useFactory: instancePerContainerCachingFactory(c => c.resolve(Foo)); } ``` -------------------------------- ### Predicate Aware Class Factory in TypeScript Source: https://github.com/microsoft/tsyringe/blob/master/README.md The predicateAwareClassFactory provides conditional object resolution based on a predicate. It can cache the result by default or resolve a fresh instance each time. This is useful for implementing strategies or conditionally injecting different implementations. ```TypeScript import {predicateAwareClassFactory} from "tsyringe"; { token: "FooHttp", useFactory: predicateAwareClassFactory( c => c.resolve(Bar).useHttps, // Predicate for evaluation FooHttps, // A FooHttps will be resolved from the container if predicate is true FooHttp // A FooHttp will be resolved if predicate is false ); } ``` -------------------------------- ### Transforming Injected Arrays with @injectAllWithTransform() in TypeScript Source: https://github.com/microsoft/tsyringe/blob/master/README.md Illustrates using @injectAllWithTransform() to apply a transformation to an array of resolved dependencies. This is useful for mapping or folding arrays of injected objects into a different type, such as an array of strings. ```typescript @injectable() class Foo { public value; } class FooTransform implements Transform{ public transform(foos: Foo[]): string[]{ return foos.map(f => f.value)); } } @injectable() class Bar { constructor(@injectAllWithTransform(Foo, FooTransform) stringArray: string[]) { // ... } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.