Home > Software engineering >  How to alter multiple functions of an object at once?
How to alter multiple functions of an object at once?

Time:11-15

I have an object that looks like this:

export declare interface Logger {
  info(msg: string, options?: LogOptions): void;
  warn(msg: string, options?: LogOptions): void;
  warnOnce(msg: string, options?: LogOptions): void;
  error(msg: string, options?: LogOptions): void;
  clearScreen(type: LogType): void;
  hasErrorLogged(error: Error | RollupError): boolean;
  hasWarned: boolean;
}

I want to create a new object that has all the same properties but with altered info, warn, warnOnce and error functions. The changes to each function are the same.

I tried the following but TypeScript says Element implicitly has an 'any' type because expression of type 'string | number | symbol' can't be used to index type:

const alterMsg = (msg: string) => msg.replaceAll('A', 'B');
const alterOptions = {
  flag: false,
};

const logger: Logger = createLogger();
const { clearScreen, hasErrorLogged, hasWarned, ...functionsToAlter } = logger;

Object.keys(functionsToAlter).forEach(key => {
  const originalFunction = functionsToAlter[key as keyof Partial<Logger>];
  const alteredFunction = (msg: string, options?: LogOptions) =>
    originalFunction(alterMsg(msg), {
      ...alterOptions,
      ...options,
    });
  functionsToAlter[key as keyof Partial<Logger>] = alteredFunction;
});

const newLogger: Logger = {
  ...functionsToChange,
  ...logger,
};

The type should stay the same. It is still the same object structure and each of the functions still accepts a string msg and an optional options object.

CodePudding user response:

Kind of partial solution:

Based on this answer https://stackoverflow.com/a/50593801/5089567 typing destructuration helps infer functionsToChange's type

const { clearScreen, hasErrorLogged, hasWarned, ...functionsToChange }: Logger & Partial<Logger> = logger;

Then instead of

key as keyof Partial<Logger>

use

key as keyof Omit<Logger, 'clearScreen' | 'hasErrorLogged' | 'hasWarned'>

And finally

const newLogger: Logger = {
  clearScreen, hasErrorLogged, hasWarned,
  ...functionsToChange,
};

Works fine in playground

  • Related