title: Keep type information after hydrating a function
body: <p>So, I have a bunch (hundreds) od dbMethods that are basically methods that take &quot;db&quot; as the first argument and then only turn to real methods. Later they are &quot;hydrated&quot; (the db is supplied), thus new methods are created.</p>
  <p>My main problem is that I want the &quot;hydrated&quot; to be properly typed. Currently it's not, because reduce() loses type information. Do you have any suggestion? I'm sharing my attempts, but &quot;RemoveFirstArgument&quot; doesn't seem to be working.</p>
  <pre><code>const dbMethods = { // db is always the first argument
      getModerators: (db: any) =&gt; (chatId: string) =&gt; Promise.resolve([111]),
      getRooms: (db: any) =&gt; (accountId: string) =&gt; Promise.resolve([222])
  }
  
  type dbkeys = keyof typeof dbMethods
  
  type WithDb = (db: any) =&gt; (...args: any) =&gt; any
  
  type DbMethodContainer = {
    [key in dbkeys]: WithDb;
  };
  
  type RemoveFirstArgument&lt;T = DbMethodContainer&gt; = {
      [P in keyof T]: ReturnType&lt;T[P]&gt;;
  };
  
  // ultimately I want &quot;hydrated&quot; to have the right type
  const hydrated: RemoveFirstArgument&lt;typeof dbMethods&gt; = Object.keys(dbMethods)
      .reduce((acc, method) =&gt; ({ ...acc, [method]: dbMethods[method](db) }), {})
  
  
  // this is how I want to use it
  const rooms = hydrated.getRooms('some accountId')
  </code></pre>
  <p><a href="https://www.typescriptlang.org/play?target=7&amp;ssl=28&amp;ssc=1&amp;pln=1&amp;pc=1#code/LAKAxg9gdgzgLgAgCYCMCyBTOALCSYIC8CA3ggPTnIoICWBAhgDYDuDAngThggGa0AneAgYCA5gFcAthihxQCRQjFY0eDAIZwIQgFwIAFKn0Mo7AJREAfIbDYtASST74A2lDGXCNgAoCIUvQYAHQCGDAQTABuGAYA2gCMSQC65gA0CkoqcABKEAEw%20kYoJmZeNgYMYJASck4ucG4e5Qh%20AUGh4ZEx8QBM-amgAL6goHDsAA48qADWGJxECHPsELwI41Or1Jg4eDCjIBs8AOq0OAAiNMTFpRbWhsGPomKFImX3puwHRwiXO7hIADC0DgDHcGkWJEycWWdCg1GWMGS%20lOFxQAG5hpiQGNJjwchgpBAYgAxQTwACC4mksjgAB4ACqLP5YAHAuRgqAaGzEKEgJQIOI%20OFLeZbBnIhAEuASARQBl4xlC5JWbFDbGgSgICRMOC0KRaDBMdgIBwINhyBAAImw7CQmjgGCQVvWEAQ9hi62wPDcYmwiCOoEgsEQtvthucUsJxIwZKEcCpkhkcjpRy2qH%20ex5CAA8igAFYYMBwYKI4qZ-DmTKKTpICRgWKVappBAyXZIFoGMiPYJVMAtuJtgGSjOsvaDsdIZLFSxDdKkOcHTVUHD0OgEXAsU3m0wBt0SGA8M5B6DCfwFRZhh1O4LZPIFAwAcgiMhE1QgtTgTkfVZxf6AA" rel="nofollow noreferrer">Here's the playground</a></p>