Augment abstract method in typescript

I have abstract class Command with abstract method “execute()“. A lot of other commands extend it. Each has its own “execute()” implementation.

How can I add some common logic (like logging) each time when any command gets executed?

export abstract class Command {
    public abstract execute(...commandParams: any[]): void;
}

Answer

In my opinion the best way to handle this is at the point where you call the execute method rather than inside the method itself.

You’re not going to get good typechecking on your execute function arguments since they are defined as ...commandParams: any[]. This is a place where we can make use of generics to enforce that all Command types fit a general interface while also not losing information about their unique arguments.

FYI, This could just as well be an interface instead of an abstract class.

interface Command<T extends any[]> {
    execute( ...commandParams: T): void;
    toString(): string;
}

class Executer {
    execute<T extends any[]>( command: Command<T>, ...args: T ) {
        command.execute(...args);
    }
    
    executeAndLog<T extends any[]>( command: Command<T>, ...args: T ) {
        console.log( `executing command ${command.toString()} with arguments:`, ...args );
        command.execute(...args);
    }
}

Playground Link

The generic T in the Executer says that we can pass in any type of Command, but that the arguments have to match the expected arguments for that specific command type.

Leave a Reply

Your email address will not be published. Required fields are marked *