Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to alter multiple functions of an object at once?

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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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.

>Solution :

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

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading