Is there any typescript framework which allow user, to use well-known from java-spring autowiring? Example
class A {
public print() : void;
}
class B {
constructor(a : A)
}
var obj = CONTAINER.get("B");
And container is part of API
I have developed an IoC container called InversifyJS with advanced dependency injection features like contextual bindings.
You need to follow 3 basic steps to use it:
The annotation API is based on Angular 2.0:
import { injectable, inject } from "inversify";
@injectable()
class Katana implements IKatana {
public hit() {
return "cut!";
}
}
@injectable()
class Shuriken implements IShuriken {
public throw() {
return "hit!";
}
}
@injectable()
class Ninja implements INinja {
private _katana: IKatana;
private _shuriken: IShuriken;
public constructor(
@inject("IKatana") katana: IKatana,
@inject("IShuriken") shuriken: IShuriken
) {
this._katana = katana;
this._shuriken = shuriken;
}
public fight() { return this._katana.hit(); };
public sneak() { return this._shuriken.throw(); };
}
The binding API is based on Ninject:
import { Kernel } from "inversify";
import { Ninja } from "./entities/ninja";
import { Katana } from "./entities/katana";
import { Shuriken} from "./entities/shuriken";
var kernel = new Kernel();
kernel.bind<INinja>("INinja").to(Ninja);
kernel.bind<IKatana>("IKatana").to(Katana);
kernel.bind<IShuriken>("IShuriken").to(Shuriken);
export default kernel;
The resolution API is based on Ninject:
import kernel = from "./inversify.config";
var ninja = kernel.get<INinja>("INinja");
expect(ninja.fight()).eql("cut!"); // true
expect(ninja.sneak()).eql("hit!"); // true
The latest release (2.0.0) supports many use cases:
You can learn more about it at https://github.com/inversify/InversifyJS
Autowiring in compiled programming languages like C# looks as the following:
kernel.Scan(scanner =>
{
// look for types in this assembly
scanner.FromCallingAssembly();
// make ISomeType bind to SomeType by default (remove the 'I'!)
scanner.BindWith<DefaultBindingGenerator>();
});
or
kernel.Bind(
x => x.FromThisAssembly()
.SelectAllClasses()
.BindAllInterfaces());
In TypeScript and JavaScript there are no assemblies. We could create a task that search across your modules for classes with the @injectable() decorator but that would be really inefficient.
We are working on an extension for InversifyJS that allows something that we think is like a sort of pseudo autowiring.
Instead of:
@injectable()
class Katana implements IKatana {
public hit() {
return "cut!";
}
}
kernel.bind<IKatana>("IKatana").to(Katana);
You can write:
@provide(Katana)
class Katana implements IKatana {
public hit() {
return "cut!";
}
}
The @provide() decorator generates the binding under the hood:
kernel.bind<Katana>(Katana).to(Katana);
The extension also includes a helper called autoProvide that applies the @provide decorator to all the entities for you.
import * as entites from "../entities";
let kernel = new Kernel();
autoProvide(kernel, entites);
let warrior = kernel.get<Warrior>(entites.Warrior);
The entities module must provide direct access to all your entities:
export { default as Warrior } from "./warrior";
export { default as Katana } from "./katana";
And the entities don't need the @injectable or @provide decorators:
class Katana {
public use() {
return "Using Katana...";
}
}
export default Katana;
However, the @inject decorator is needed:
import Katana from "./katana";
import { inject } from "inversify";
class Warrior {
private _weapon: Katana;
public constructor(
// we need to declare binding because auto-provide uses
// @injectbale decorator at runtime not compilation time
// in the future maybe this limitation will desapear
// thanks to design-time decorators or some other TS feature
@inject(Katana) weapon: Katana
) {
this._weapon = weapon;
}
public fight() {
return this._weapon.use();
}
}
export default Warrior;
As I said, this is not autowiring because without assemblies is impossible but it is close enough.
You can learn more about inversify-binding-decorators here.
You can also checkout Angular2 DI
https://github.com/angular/di.js
there is also few examples: https://github.com/angular/di.js/tree/master/example/kitchen-di