Skip to content

Instantly share code, notes, and snippets.

@nathggns
Last active August 29, 2015 14:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nathggns/e4b0c933f9176cc38cb6 to your computer and use it in GitHub Desktop.
Save nathggns/e4b0c933f9176cc38cb6 to your computer and use it in GitHub Desktop.
Class-based injection in typescript

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']);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment