or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

decorators.mddependency-container.mdfactories.mdindex.mdlazy-loading.mdlifecycle-management.mdproviders.md
tile.json

tessl/npm-tsyringe

Lightweight dependency injection container for JavaScript/TypeScript

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/tsyringe@4.10.x

To install, run

npx @tessl/cli install tessl/npm-tsyringe@4.10.0

index.mddocs/

TSyringe

TSyringe is a lightweight dependency injection container for TypeScript/JavaScript that enables constructor injection for building modular, testable applications. It provides comprehensive decorators for marking classes and parameters, supports multiple provider types for flexible service registration, and offers advanced features like scoped lifecycles, child containers, and interception hooks.

Package Information

  • Package Name: tsyringe
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install tsyringe reflect-metadata

Core Imports

import "reflect-metadata"; // Required polyfill
import { container, injectable, singleton, inject } from "tsyringe";

For CommonJS:

require("reflect-metadata");
const { container, injectable, singleton, inject } = require("tsyringe");

Note: TSyringe requires the reflect-metadata polyfill to be imported at the top of your entry point.

Basic Usage

import "reflect-metadata";
import { container, injectable, singleton, inject } from "tsyringe";

// Define services
@injectable()
class Logger {
  log(message: string) {
    console.log(message);
  }
}

@injectable()
class UserService {
  constructor(private logger: Logger) {}
  
  getUser(id: string) {
    this.logger.log(`Getting user ${id}`);
    return { id, name: "John Doe" };
  }
}

// Register and resolve
container.register("UserService", UserService);
const userService = container.resolve<UserService>("UserService");
const user = userService.getUser("123");

Architecture

TSyringe is built around several key components:

  • Dependency Container: Core container interface for registration and resolution with hierarchical child container support
  • Decorator System: Comprehensive decorators (@injectable, @singleton, @inject, etc.) for marking classes and dependencies
  • Provider System: Flexible provider types (class, value, factory, token) for different dependency registration patterns
  • Lifecycle Management: Multiple lifecycle scopes (transient, singleton, container-scoped, resolution-scoped)
  • Lazy Loading: DelayedConstructor and delay utilities for lazy dependency initialization
  • Interception: Pre/post resolution hooks for advanced dependency customization

Capabilities

Dependency Container

Core container interface providing dependency registration, resolution, and lifecycle management. Supports hierarchical child containers and disposal patterns.

interface DependencyContainer extends Disposable {
  // Registration methods (overloaded)
  register<T>(token: InjectionToken<T>, provider: Provider<T>, options?: RegistrationOptions): DependencyContainer;
  
  // Singleton registration
  registerSingleton<T>(from: InjectionToken<T>, to: InjectionToken<T>): DependencyContainer;
  registerSingleton<T>(token: constructor<T>): DependencyContainer;
  
  // Type registration
  registerType<T>(from: InjectionToken<T>, to: InjectionToken<T>): DependencyContainer;
  
  // Instance registration
  registerInstance<T>(token: InjectionToken<T>, instance: T): DependencyContainer;
  
  // Resolution methods
  resolve<T>(token: InjectionToken<T>): T;
  resolveAll<T>(token: InjectionToken<T>): T[];
  
  // Registration check
  isRegistered<T>(token: InjectionToken<T>, recursive?: boolean): boolean;
  
  // Container management
  reset(): void;
  clearInstances(): void;
  createChildContainer(): DependencyContainer;
  
  // Interception
  beforeResolution<T>(
    token: InjectionToken<T>, 
    callback: PreResolutionInterceptorCallback<T>, 
    options?: InterceptorOptions
  ): void;
  afterResolution<T>(
    token: InjectionToken<T>, 
    callback: PostResolutionInterceptorCallback<T>, 
    options?: InterceptorOptions
  ): void;
}

// Global container instance
const container: DependencyContainer;

Dependency Container

Class Decorators

Decorators for marking classes as injectable, defining lifecycle behavior, and configuring automatic registration.

function injectable<T>(options?: {token?: InjectionToken<T> | InjectionToken<T>[]}): ClassDecorator;
function singleton<T>(): ClassDecorator;
function scoped<T>(lifecycle: Lifecycle.ContainerScoped | Lifecycle.ResolutionScoped, token?: InjectionToken<T>): ClassDecorator;
function autoInjectable(): ClassDecorator;
function registry(registrations: ({token: InjectionToken; options?: RegistrationOptions} & Provider<any>)[]): ClassDecorator;

Decorators

Parameter Decorators

Decorators for parameter-level dependency injection, enabling fine-grained control over individual constructor and method parameters.

function inject(token: InjectionToken<any>, options?: {isOptional?: boolean}): ParameterDecorator;
function injectAll(token: InjectionToken<any>, options?: {isOptional?: boolean}): ParameterDecorator;
function injectWithTransform(
  token: InjectionToken<any>, 
  transformer: InjectionToken<Transform<any, any>>, 
  ...args: any[]
): ParameterDecorator;
function injectAllWithTransform(
  token: InjectionToken<any>, 
  transformer: InjectionToken<Transform<[any], any>>, 
  ...args: any[]
): ParameterDecorator;

Provider System

Flexible provider types for registering dependencies using different patterns (class constructors, factory functions, concrete values, or token aliases).

type Provider<T> = ClassProvider<T> | FactoryProvider<T> | ValueProvider<T> | TokenProvider<T>;

interface ClassProvider<T> {
  useClass: constructor<T> | DelayedConstructor<T>;
}

interface FactoryProvider<T> {
  useFactory: (dependencyContainer: DependencyContainer) => T;
}

interface ValueProvider<T> {
  useValue: T;
}

interface TokenProvider<T> {
  useToken: InjectionToken<T>;
}

Provider System

Lifecycle Management

Comprehensive lifecycle management with multiple scopes, registration options, and disposable resource handling.

enum Lifecycle {
  Transient = 0,
  Singleton = 1,
  ResolutionScoped = 2,
  ContainerScoped = 3
}

interface RegistrationOptions {
  lifecycle: Lifecycle;
}

interface Disposable {
  dispose(): Promise<void> | void;
}

Lifecycle Management

Factory Functions

Advanced factory utilities for caching strategies and conditional instantiation patterns.

type FactoryFunction<T> = (dependencyContainer: DependencyContainer) => T;

function instanceCachingFactory<T>(factoryFunc: FactoryFunction<T>): FactoryFunction<T>;
function instancePerContainerCachingFactory<T>(factoryFunc: FactoryFunction<T>): FactoryFunction<T>;
function predicateAwareClassFactory<T>(
  predicate: (dependencyContainer: DependencyContainer) => boolean,
  trueConstructor: constructor<T>,
  falseConstructor: constructor<T>,
  useCaching?: boolean
): FactoryFunction<T>;

Factory Functions

Lazy Loading

Lazy initialization utilities for circular dependency resolution and delayed constructor instantiation.

function delay<T>(wrappedConstructor: () => constructor<T>): DelayedConstructor<T>;

class DelayedConstructor<T> {
  createProxy(createObject: (ctor: constructor<T>) => T): T;
}

Lazy Loading

Types

// Core injection token type
type InjectionToken<T> = constructor<T> | string | symbol | DelayedConstructor<T>;

// Constructor function type
type constructor<T> = {new (...args: any[]): T};

// Frequency for interceptors
type Frequency = "Always" | "Once";

// Resolution types
type ResolutionType = "Single" | "All";

// Interceptor callback types
type PreResolutionInterceptorCallback<T> = (
  token: InjectionToken<T>, 
  resolutionType: ResolutionType
) => void;

type PostResolutionInterceptorCallback<T> = (
  token: InjectionToken<T>, 
  result: T | T[], 
  resolutionType: ResolutionType
) => void;

// Interceptor options
interface InterceptorOptions {
  frequency: Frequency;
}

// Transform interface for dependency transformation
interface Transform<TIn, TOut> {
  transform: (incoming: TIn, ...args: any[]) => TOut;
}

// Factory function type
type FactoryFunction<T> = (dependencyContainer: DependencyContainer) => T;