TypeScript Hack the original behavior

eye-catchJavaScript/TypeScript

Dependency doesn’t support what you want? Then, hacking the code might be the solution. This article tries to replace the original behavior with what we want.

Sponsored links

Replace original function

For example, let’s assume that the following class is provided by a dependent module.

export class ClassToBeReplaced {
    public currentState(): string {
        return `current path is ${this.getCurrent()}, internalState: ${this.internalState()}`;
    }
    public getCurrent(): string {
        return "current-path";
    }
    private internalState(): number {
        return 11;
    }
}

const instance = new ClassToBeReplaced();
console.log(`getCurrent: ${instance.getCurrent()}`);
console.log(`currentState: ${instance.currentState()}`);
// getCurrent: current-path
// currentState: current path is current-path, internalState: 11

If we want to change the original behavior we can do it in the following way.

function hack(callback: () => void) {
    const originalGetCurrent = instance.getCurrent;
    const originalInternalState = (instance as any).internalState;
    try {
        instance.getCurrent = () => "hacked-path";
        (instance as any).internalState = () => 5000;

        callback();
    } finally {
        instance.getCurrent = originalGetCurrent;
        (instance as any).internalState = originalInternalState;
    }
}

It stores the original functions in a temp variable and assign the new function. They should be called in the callback function. The point is to make it any when the target function is private. The usage is as follows.

hack(() => {
    console.log(`getCurrent: ${instance.getCurrent()}`);
    console.log(`currentState: ${instance.currentState()}`);
});
// getCurrent: hacked-path
// currentState: current path is hacked-path, internalState: 5000

Why is it necessary?

It’s hard to cover all scenarios. Therefore, a module might not have the function that we want especially if the module is really big. There is a possibility that we just don’t know how to do it in the proper way but it is sometimes very hard to find it because of a lack of documentation.

Writing an issue is another way but we don’t know how long it takes to fix the problem.

In my case, I needed to create an object under a specific object. The class has big objects and I needed to find a target object, then add a new object to it. However, the process is basically done under the hood, in the class. Therefore, I have no control to select the target object.

By the way, the module consists of about 20 modules.

But a public function to get an object is used in a function that creates a new object to it. In the function to create a new object, the object is always the same for some reason. I needed to replace the behaviour to be able to get the target object in the function.

End

It is I guess rare case to need to replace the original behavior but it might be helpful for you to know this hack.

Comments

Copied title and URL