Requires building the master branch of TypeScript, and the reflect-metadata polyfill.
Compile with
node built/local/tsc.js --target ES5 --experimentalDecorators --emitDecoratorMetadata --module commonjs inject.ts
/// <reference path="node_modules/reflect-metadata/reflect-metadata.d.ts" /> | |
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { | |
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc); | |
switch (arguments.length) { | |
case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target); | |
case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0); | |
case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc); | |
} | |
}; | |
var __metadata = (this && this.__metadata) || function (k, v) { | |
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); | |
}; | |
require('reflect-metadata'); | |
function inject(target) { | |
} | |
var SomeClass = (function () { | |
function SomeClass() { | |
this.value = 'SomeClassValue'; | |
} | |
return SomeClass; | |
})(); | |
var SomeOtherClass = (function () { | |
function SomeOtherClass() { | |
this.value = 'SomeOtherClassValue'; | |
} | |
return SomeOtherClass; | |
})(); | |
var Injector = (function () { | |
function Injector(typeMap) { | |
this.typeMap = typeMap; | |
} | |
Injector.prototype.call = function (obj, method, extraArgs) { | |
var _this = this; | |
if (extraArgs === void 0) { extraArgs = []; } | |
var result = Reflect.getMetadata('design:paramtypes', obj.constructor.prototype, method); | |
if (typeof result === 'undefined') { | |
result = []; | |
} | |
if (result instanceof Array) { | |
return obj[method].apply(obj, result.map(function (item) { | |
var val = _this.typeMap.get(item) || extraArgs.shift(); | |
if (!val) { | |
throw new Error('Could not get type info for ' + item); | |
} | |
return val; | |
})); | |
} | |
else { | |
throw new Error('Could not get type info'); | |
} | |
}; | |
return Injector; | |
})(); | |
var MyClass = (function () { | |
function MyClass() { | |
} | |
MyClass.prototype.myMethod = function (aClass, anotherClass, somePassedValue) { | |
console.log(aClass.value); | |
// SomeClassValue | |
console.log(anotherClass.value); | |
// SomeOtherClassValue | |
console.log(somePassedValue); | |
// Hello, World | |
}; | |
Object.defineProperty(MyClass.prototype, "myMethod", | |
__decorate([ | |
inject, | |
__metadata('design:type', Function), | |
__metadata('design:paramtypes', [SomeClass, SomeOtherClass, Object]), | |
__metadata('design:returntype', Object) | |
], MyClass.prototype, "myMethod", Object.getOwnPropertyDescriptor(MyClass.prototype, "myMethod"))); | |
return MyClass; | |
})(); | |
var map = new Map(); | |
map.set(SomeClass, new SomeClass()); | |
map.set(SomeOtherClass, new SomeOtherClass()); | |
var injector = new Injector(map); | |
injector.call(new MyClass(), 'myMethod', ['Hello, World']); |
/// <reference path="node_modules/reflect-metadata/reflect-metadata.d.ts" /> | |
import 'reflect-metadata'; | |
declare class Map<K, V> { | |
get(key : K): V; | |
set(key : K, value : V); | |
} | |
function inject(target) { | |
} | |
class SomeClass { | |
value = 'SomeClassValue'; | |
} | |
class SomeOtherClass { | |
value = 'SomeOtherClassValue'; | |
} | |
class Injector { | |
constructor(private typeMap : Map<Function, Object>) { | |
} | |
call(obj : Object, method : string, extraArgs : any[] = []) : any { | |
var result : any[] | void = Reflect.getMetadata('design:paramtypes', obj.constructor.prototype, method); | |
if (typeof result === 'undefined') { | |
result = []; | |
} | |
if (result instanceof Array) { | |
return obj[method]( | |
...result.map(item => { | |
var val = this.typeMap.get(item) || extraArgs.shift(); | |
if (!val) { | |
throw new Error('Could not get type info for ' + item) | |
} | |
return val; | |
}) | |
); | |
} else { | |
throw new Error('Could not get type info'); | |
} | |
} | |
} | |
class MyClass { | |
@inject | |
public myMethod(aClass : SomeClass, anotherClass : SomeOtherClass, somePassedValue : any) { | |
console.log(aClass.value); | |
// SomeClassValue | |
console.log(anotherClass.value); | |
// SomeOtherClassValue | |
console.log(somePassedValue); | |
// Hello, World | |
} | |
} | |
var map = new Map(); | |
map.set(SomeClass, new SomeClass()); | |
map.set(SomeOtherClass, new SomeOtherClass()); | |
var injector = new Injector(map); | |
injector.call(new MyClass(), 'myMethod', ['Hello, World']); |