TypeScript decorators with additional arguments

Angular provides a fancy way to overwrite constructors with additional parameters using TypeScript decorators. Every Angular developer for sure knows the pattern
@NgModule({ imports: [], declarations: [] }) export const MyModule {}
In a current project I implemented a server side / electron application with inversifyJS to get a similar dependency injection system to Angulars. But the TypeScript documentation does not provide a way to handle decorator function parameters. So I decided to get myself into it and dig a little deeper. It turned out that this is actually really simple.
The difference to simple decorators is really easy to understand. Instead of a decorator function we implement a function that returns a decorator function and is able to catch the arguments of the first function. For example
function classDecorator(data: DecoratorData) { return function <T extends { new(...args: any[]): {} }>(constructor: T) { return class extends constructor { a = "decorators"; b = "are"; d = data; // or whatever you want to do with data }; }; }
the classDecorator function receives the decorator data we want to pass in as a custom TypeScript datatype, here DecoratorData. The function returns a new function, the wanted decorator function (as described in the official docs). This function is now able to read the data parameter of the outer function. In this way we are able to work with that data and create new objects or variables with it. Afterwards one can simply use it in the known Angular way
@classDecorator({ data: "cool" }) class MyObject { b = "are not"; c: string; constructor(param: string) { this.c = param; } }
Here the @classDecorator is used to overwrite the constructor of the MyObject class. The resulting MyObject instance instanciated with
const myObj = new MyObject("super");
now contains the decorator and the constructor parameter data. Printing the instance to a console will output something like the following
{ a: 'decorators', b: 'are', c: 'super', d: 'cool' }

Comments

Any questions? Want to join the discussion?

Sign in or sign up