0

Given an object with nested objects and functions like so:

const commands: {
 doSomething: () => 'Yo',
 table: {
   rows: () => 10,
   columns: () => 6,
   name: ( name: string) => name + ' hello'
 },
 doSomethingElse: () => 'Boo',
 modal: {
   sub: {
      hello: () => 'hello'
   }
 }
}

I would like to call a function that returns a flat object like so:

const mappedCommands = {
 doSomething: () => 'Yo',
 table_rows: () => 10,
 table_columns: () => 6,
 table_name: ( name: string) => name + ' hello'
 doSomethingElse: () => 'Boo',
 modal_sub_hello: () => 'hello'
}

I would also like this typed. So when I do:

type Commands = typeof mappedCommands

I would get the type:

{
 doSomething: () => string,
 table_rows: () => number,
 table_columns: () => number,
 table_name: (name: string) => string
 doSomethingElse: () => string,
 modal_sub_hello: () => string
}

I've currently got as far as writing this, but it's not typed.

const createCommands = <N extends string, T extends Record<string, any>>(inputs: T, prepend: N) => {
  const mappedCommands: Record<string, any> = {};
  // for each command
  Object.keys(inputs).forEach((key) => {
    const current = inputs[key];
    if (typeof current === 'function') {
      mappedCommands[`${prepend}${key}`] = inputs[key];
    } else {
      const subCommands = createCommands(current, `${key}_`);
      // we add them to the level above.
      Object.keys(subCommands).forEach((key) => {
        mappedCommands[`${prepend}${key}`] = subCommands[key];
      });
    }
  });
  return mappedCommands;
};

I've asked a few related questions, but I think this would be a better solution if I can get it working.

Related questions:

Typescript - Type that Map keys and flatten objects

Typescript Type - append string for each key in object

Ewan
  • 378
  • 3
  • 14
  • 1
    Try some of the answers [here](https://stackoverflow.com/questions/65919016/how-can-an-object-type-with-nested-subproperties-be-flattened) first. – kelsny Nov 03 '22 at 13:00
  • Seems to work: https://tsplay.dev/mbQ93N – kelsny Nov 03 '22 at 13:12
  • Yeah, adapting the solution I proposed to the open question here looks like [this](https://tsplay.dev/m368qN), if we're just writing the type. Here again too, though, this sort of deeply nested thing tends to go bonkers with edge cases (optional properties, union properties, index signatures, generics, etc) and so I always hesitate to write up answers before teasing the important use cases out of OP. Otherwise you get the "this is great, except one thing that doesn't work, I need it to work for ${EDGE_CASE_WHICH_REQUIRES_COMPLETE_REFACTORING_TO_HANDLE}". – jcalz Nov 03 '22 at 15:16

0 Answers0