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;
}
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);
}
}
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.