3
\$\begingroup\$

I have a Typescript decorator that traces method calls. The decorator can be applied at both the class level and method level. I want to disable the decorator in production. Is this code the most correct way to bypass the decorator?

let enabled = process.env.NODE_ENV !== "production"

export function Trace() {

    var printIn = (className: string, methodName: string, args: any[]) => {
        console.debug("=> %s.%s(" + args.map(val => "%s").join(", ") + ")", className, methodName, JSON.stringify(args));
    };

    var printOut = (className: string, methodName: string, ret: any) => {
        console.debug("<= %s.%s: %s", className, methodName, ret);
    };

    return (target: any, name?: string, descriptor?: any) => {

// This line is here is how i'm trying to bypass the decorator.

        // Don't wrap if disabled
        if (!enabled) return target

        if (descriptor) {

            // decorating a method
            let original = descriptor.value;

            descriptor.value = function (...args: any[]) {

                printIn(target.constructor.name, name, args);
                let ret = original.apply(this, args);
                printOut(target.constructor.name, name, ret);

                return ret;
            }

            return descriptor;

        } else {

            // decorating a class
    Object.getOwnPropertyNames(target.prototype).forEach((methodName: string) => {

                if (methodName === "constructor") {
                    return;
                }

                let original = target.prototype[methodName];

                if (typeof original !== "function") {
                    return;
                }

                // an arrow function can't be used while we have to preserve right 'this'
                target.prototype[methodName] = function (...args: any[]) {

                    printIn(target.name, methodName, args);
                    let ret = original.apply(this, args);
                    printOut(target.name, methodName, ret);

                    return ret;
                };
            });

            return target;
        }
    };
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.