
Product
Announcing Socket Certified Patches: One-Click Fixes for Vulnerable Dependencies
A safer, faster way to eliminate vulnerabilities without updating dependencies
@decaf-ts/injectable-decorators
Advanced tools
injectable decorators extension for decorator validation
A lightweight TypeScript dependency injection library that provides decorators for marking classes as injectable singletons and injecting dependencies into class properties. It features a centralized registry for managing dependencies, lazy loading of injected properties, and support for custom transformations of injected instances.
Documentation available here
Minimal size: 1.4 KB kb gzipped
The injectable-decorators library is a standalone module that provides a lightweight and flexible dependency injection system for TypeScript applications. It is designed to simplify the management of dependencies between components in your application through the use of TypeScript decorators.
Injectables Registry
Decorators
@injectable(): Class decorator that marks a class as available for dependency injection
@inject(): Property decorator that injects a dependency into a class property
Reflection Utilities
The library follows a minimalist approach, focusing on providing essential dependency injection capabilities without unnecessary complexity. It's designed to be:
Unlike more complex DI frameworks, this library doesn't require extensive configuration or setup. The developer is responsible for initially decorating classes and properties, but the library handles the instantiation and injection process automatically.
Description: Define a class with @injectable() so it becomes available through the central registry. Creating with new returns the instance managed by the registry.
import 'reflect-metadata';
import { injectable, Injectables } from 'injectable-decorators';
@injectable()
class InitialObject {
doSomething() { return 5; }
}
const obj = new InitialObject();
const same = Injectables.get(InitialObject);
// obj and same refer to the same instance (singleton by default)
Description: Use @inject() on a typed property. The instance is created lazily when the property is first accessed and cached thereafter.
import 'reflect-metadata';
import { injectable, inject, Injectables } from 'injectable-decorators';
@injectable()
class SomeService { value = 5; }
class Controller {
@inject()
service!: SomeService; // non-null assertion because it's set outside the constructor
}
const c = new Controller();
console.log(c.service.value); // 5
console.log(c.service === Injectables.get(SomeService)); // true
Description: Provide a stable name when class names may change (e.g., minification) or to upcast through a base type.
import 'reflect-metadata';
import { injectable, inject, singleton } from 'injectable-decorators';
@singleton()
class AAA { a = 'aaa'; }
@injectable('AAA')
class BBB extends AAA { b = 'bbb'; }
const b = new BBB();
class Host {
@inject()
repo!: AAA; // resolves to the instance registered under category 'AAA'
}
const h = new Host();
console.log(h.repo === b); // true
Description: When a different string category was used at registration, pass that string to @inject.
import 'reflect-metadata';
import { inject, singleton } from 'injectable-decorators';
class DDD { a = 'aaa'; }
@singleton('EEE')
class CCC extends DDD { b = 'bbb'; }
const instance = new CCC();
class Holder {
@inject('EEE')
repo!: CCC;
}
const h = new Holder();
console.log(h.repo === instance); // true
Description: You can register an injectable using another constructor as the category, then inject it by that constructor.
import 'reflect-metadata';
import { injectable, inject } from 'injectable-decorators';
class Token {}
@injectable(Token, { callback: (original) => original })
class Impl {
id = 1;
}
class UsesImpl {
@inject(Token)
object!: Impl; // injects the instance registered under Token (Impl instance)
}
const u = new UsesImpl();
console.log(u.object instanceof Impl); // true
Description: Use @onDemand() so each injection produces a fresh instance. You can pass args for construction via @inject({ args }).
import 'reflect-metadata';
import { onDemand, inject } from 'injectable-decorators';
@onDemand()
class FreshObject {
constructor(public a?: string, public b?: string) {}
}
class ParentA {
@inject()
fresh!: FreshObject; // new instance per parent
}
class ParentB {
@inject({ args: ['x', 'y'] })
fresh!: FreshObject; // passes constructor args to on-demand instance
}
const p1 = new ParentA();
const p2 = new ParentA();
console.log(p1.fresh !== p2.fresh); // true
const p3 = new ParentB();
console.log([p3.fresh.a, p3.fresh.b]); // ['x','y']
Description: Modify the resolved instance before assignment using a transformer.
import 'reflect-metadata';
import { injectable, inject } from 'injectable-decorators';
@injectable('SomeOtherObject')
class SomeOtherObject { value() { return 10; } }
class Controller {
@inject({ transformer: (obj: SomeOtherObject, c: Controller) => '1' })
repo!: SomeOtherObject | string;
}
const c = new Controller();
console.log(c.repo); // '1'
Description: Reset clears all registrations. Swapping the registry replaces the storage, losing previous entries.
import { Injectables, InjectableRegistryImp } from 'injectable-decorators';
// ensure something is registered
Injectables.get('SomeOtherObject');
// swap to a fresh registry
Injectables.setRegistry(new InjectableRegistryImp());
console.log(Injectables.get('SomeOtherObject')); // undefined
// reset to a new empty default registry
Injectables.reset();
Description: Prefer @singleton() to force single instance, or @onDemand() for new instance per retrieval.
import { singleton, onDemand } from 'injectable-decorators';
@singleton()
class OneOnly {}
@onDemand()
class Many {}
Description: Generate reflection keys and understand default config.
import { getInjectKey } from 'injectable-decorators';
console.log(getInjectKey('injectable')); // "inject.db.injectable"
console.log(getInjectKey('inject')); // "inject.db.inject"
Notes:
import 'reflect-metadata' once in your app before using decorators.
If you have bug reports, questions or suggestions please create a new issue.
I am grateful for any contributions made to this project. Please read this to get started.
The first and easiest way you can support it is by Contributing. Even just finding a typo in the documentation is important.
Financial support is always welcome and helps keep both me and the project alive and healthy.
So if you can, if this project in any way. either by learning something or simply by helping you save precious time, please consider donating.
This project is released under the MIT License.
By developers, for developers...
FAQs
injectable decorators extension for decorator validation
We found that @decaf-ts/injectable-decorators demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 5 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Product
A safer, faster way to eliminate vulnerabilities without updating dependencies

Product
Reachability analysis for Ruby is now in beta, helping teams identify which vulnerabilities are truly exploitable in their applications.

Research
/Security News
Malicious npm packages use Adspect cloaking and fake CAPTCHAs to fingerprint visitors and redirect victims to crypto-themed scam sites.