typescriptcompile-time-weaving

TypeScript code weaving


Is there a way to do code weaving in TypeScript?

What I'm trying to do is inject a piece of code as the very first line of every function in my TypeScript app and I don't wont to do this manually (this manual approach is tedious and error prone).


Solution

  • While not true compile-time weaving, for class methods only you can use method decorators to wrap those methods with additional functionality at runtime. Consider this example method decorator, which makes invocation also log the received arguments into the console:

    // the method decorator function
    function log(target: Object, key: string, descriptor: any) {
        // replace original property descriptor of method with the following one:
        return {
            // the new method:
            value: function (...args: any[]) {
                // log arguments
                console.log(args);
    
                // invoke the original method as part of the new method,
                // and return its returned value (if any)
                return descriptor.value.apply(this, args);
            }
        };
    }
    

    Applying this decorator to a method is as trivial as:

    class Calculator {
        @log
        add(a: number, b: number) {
            return a + b;
        }
    }
    

    Quick explanation: a method decorator in Typescript has the following signature:

    <T>(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor<T>) => PropertyDescriptor<T> | void;
    

    In other terms, the method decorator takes in 3 arguments:

    1. The prototype object on which the original method is defined
    2. The property key of the method
    3. The property descriptor of the method

    A method decorator returns a single property descriptor, which is a replacement for that of the original method on the type.