title: How to augment interface with specific overload when it has a catch all?
body: <p>I'm trying to add a method overload signature in an interface from an <code>npm</code> package that defines several specific signatures and then a catch-all signature, but my overload doesn't get picked up when I write a call that should match it; the catch-all gets picked up instead. It <em>seems</em> to be order-related (though of course I could be wrong), as though the catch-all is getting checked against the call before my new overload is and since it matches, is being used. How can I get my overload to be picked up?</p>
  <ul>
  <li>I've ensured that I'm extending the right interface.</li>
  <li>I've &quot;proven&quot; the catch-all is the problem by commenting it out in the original module's types — when I do that, my added overload gets picked up where it didn't before. (And then if I also comment out my overload, the call shows as an error because nothing matches.)</li>
  <li>I've checked that I'm not hitting the max number of overloads. There are only six originals, plus my addition would be seven; <a href="https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgKIA84FsAOAbFAbwFgAoZC5OACgHsQIAuZEAVywCNoBKZtz6AG4ylKnQZ92XKABpkYAO61JAqLxZShIyjXpMNquYuUHpRgBZQI+-tPW2t5HeJubZ8pSrPzL1r9DkYWlYofzUw4ScKXQlTAI8TB3cwX1dDZCCQsMDgADc0uwjtaJdshLKUqwL4zNC49xg86vcAZ2B0MPs3SNEY5qNPeosqstrRprK2jqHkFoh8kE6iqLE9CsGk4b8ZsZ2JmanJ+YhFmYhgAHNzMCX6nuc1meMK1NHgus2M-c-Dg+PTz7nK43GYgUDNLqqe4lR6fZ5PV47d7jfKTdpHBZlIHXMpg2Jwk63JLQ1b4twDRLknwjJFZPaog7ov6Ys6XHGg8EVQlnAgspKQ6QkvrrSnpSrbT67SXfKm-H7-LFskGfPH9eTcwG8jVUxQQPAM-nLXqlJ4bHWIyXI+lquWyhWs4G4zlPbXpPX2uEKPUG83AKCQV2FO7FUlq+Fwi1UqVRmXpW1xj1U7HKqmqrkApNajNir36sPmP0B7PeWpFondEPC02i7zitXR9KNH1xpnyvlJpVOsliwPxd3tnPe-OF6zFmrvMt7GCTw3BlZVz01+J1t506XN7zxzeJt2djnd2u99z9o8DIcvEenjIT0fjae3xnoGduAWOY2wnVmsWRxtW9c21s7QHbxky7MMrxPMdklzDdlwLf0H0tEJn0bYB7yvKYUO3BYsJ4I0HgPZcv1rH8Sz-GNYNaQCE2Avs9xVZ0CSguRIPWc8EUvZjr2QxCY3QrjMN4miTlw48lSEoNiUrE1FxeGkkI+CiAOmNsIPo1NGJ1CCszYvMLwQq9Swkmo0NEuRBIw-4zOQZNjPcVVRNfKAhRkz8l2SUjxzXJS0RUoC1MdfdwK41jTXYiNONXAyuMafjfOsuYcLsljxKvBzko8ESAE9yyhaSP3SAA6YqsFoKwwgAbQAXScyIAF8yDIAATCAEDwOArGQAgwBs5gMGwfAIEiMgEHoFoepAZAAF4QwgQqaAARm4ZAAGpZvm6gFrkAAmZa1pWObFp2uQAGY9vWo7kG2065AAFnOg6Nq2q6buQW65AAVge0RDs247kBOu7PrkAA2b7KF+57roBoHkA+0G5AAdnBihIf+wG3uB5AQaRuQAA4UZsp70dh+Hsdx5A8bkABOQm0ZemHMbhhHkER-GabkBaAAY6eJhmMfe5nydZ9nkGpzmuc5pbVouv7+dJlm2cpjnkG5qXOd2mXHsu6GBaxnGReVsWJfV1XoYWs6tZ+vndYV4Wlap43Vcl1XnoW82MYW+6rYhm3XsFsmDYdlW1ddjXOc9wWFq+n3Ub9xmA8V0Xxed033Yjzmo7Jhawdjomdf9-WKcdlPQ4Wt2Pczzns4Nhbkbz+nbaZwPi5Dl3y-D1XI+rzna6VhaCYb+O9aFoPk5NsOzYz1Ws97zn+8dhbaaHguE6Lw2S4njup67qvVZr+fOcXlPtp5le5abxP7fH1PJ-T3eZ571W+6PzmT5d7alsiIA" rel="nofollow noreferrer">a quick check</a> suggests the limit is much higher than that.</li>
  <li>I've checked that if I set aside my <code>.d.ts</code> file for a moment and add my new overload directly to the original interface, above the catch-all, it works. <em>(Thanks for <a href="https://stackoverflow.com/questions/73090669/how-to-augment-interface-with-specific-overload-when-it-has-a-catch-all?noredirect=1#comment129089500_73090669">that suggestion</a>, Eldar)</em></li>
  <li>I've tried referencing my <code>.d.ts</code> file explicitly in <code>tsconfig.json</code> (though I suspect that doesn't make sense).</li>
  <li>I've tried referencing my <code>.d.ts</code> file via a triple-slash reference directive (though I suspect that doesn't make sense).</li>
  <li>I've tried both of the above with a simple <code>.ts</code> instead (though I suspect... ).</li>
  <li>I've looked at various questions about augmenting interfaces (<a href="https://stackoverflow.com/questions/42262565/how-to-augment-typescript-interface-in-d-ts">1</a>, <a href="https://stackoverflow.com/questions/44196107/augmenting-an-interface-that-lives-in-a-declared-namespace-in-typescript">2</a>, <a href="https://stackoverflow.com/questions/38817060/augmenting-existing-interfaces">3</a>, <a href="https://stackoverflow.com/questions/43193844/augment-imported-typescript-module-interfaces">4</a>, and others), but couldn't figure it out based on them.</li>
  </ul>
  <p>This is meant to be a general question, but a specific example helps focus the question and possible answers: The specific case is lodash's <code>extend</code> method.</p>
  <p>In <code>@types/lodash/common/object.d.ts</code>, <code>extend</code> is defined like this:</p>
  <pre class="lang-typescript prettyprint-override"><code>declare module &quot;../index&quot; {
      // ...lots of other stuff...
  
      interface LoDashStatic {
          /**
           * @see _.extend
           */
          extend&lt;TObject, TSource&gt;(object: TObject, source: TSource): TObject &amp; TSource;
          /**
           * @see _.extend
           */
          extend&lt;TObject, TSource1, TSource2&gt;(object: TObject, source1: TSource1, source2: TSource2): TObject &amp; TSource1 &amp; TSource2;
          /**
           * @see _.extend
           */
          extend&lt;TObject, TSource1, TSource2, TSource3&gt;(object: TObject, source1: TSource1, source2: TSource2, source3: TSource3): TObject &amp; TSource1 &amp; TSource2 &amp; TSource3;
          /**
           * @see _.extend
           */
          extend&lt;TObject, TSource1, TSource2, TSource3, TSource4&gt;(object: TObject, source1: TSource1, source2: TSource2, source3: TSource3, source4: TSource4): TObject &amp; TSource1 &amp; TSource2 &amp; TSource3 &amp; TSource4;
          /**
           * @see _.extend
           */
          extend&lt;TObject&gt;(object: TObject): TObject;
          /**
           * @see _.extend
           */
          extend&lt;TResult&gt;(object: any, ...otherArgs: any[]): TResult;
      }
  
      // ...lots of other stuff...
  }
  </code></pre>
  <p>As you can see, there are various overloads with specific numbers of source objects, and then a &quot;catch-all&quot; at the very end using rest syntax.</p>
  <p>Through machinations in <code>@types/lodash/index.d.ts</code> that I frankly don't understand, apparently that <code>LoDashStatic</code> interface ends up in the namespace <code>_</code>, which is where we see it when using it.</p>
  <p>I wanted to add an overload that accepts five source objects rather than topping out at four (as an example for my answer to <a href="https://stackoverflow.com/questions/73089832/">this question</a>. So in a <code>lodash-extensions.d.ts</code> file, I did this:</p>
  <pre class="lang-typescript prettyprint-override"><code>declare namespace _ {
      export interface LoDashStatic {
          tjc(): number; // ** I'll explain this below
          /**
           * @see _.extend
           */
          extend&lt;TObject, TSource1, TSource2, TSource3, TSource4, TSource5&gt;(
              object: TObject,
              source1: TSource1,
              source2: TSource2,
              source3: TSource3,
              source4: TSource4,
              source5: TSource5
          ): TObject &amp; TSource1 &amp; TSource2 &amp; TSource3 &amp; TSource4 &amp; TSource5;
      }
  }
  </code></pre>
  <p>Then in <code>test.ts</code>, I have:</p>
  <pre class="lang-typescript prettyprint-override"><code>import { extend, tjc } from &quot;lodash&quot;;
  
  const n = tjc();
  console.log(n);
  const fourSource = extend({ a: 1 }, { b: 2 }, { c: 3 }, { d: 4 }, { e: 5 });
  console.log(fourSource);
  const fiveSource = extend({ a: 1 }, { b: 2 }, { c: 3 }, { d: 4 }, { e: 5 }, { f: 6 });
  console.log(fiveSource);
  </code></pre>
  <p>The <code>tjc</code> there and in my <code>lodash-extensions.d.ts</code> is just to check that I'm augmenting the right interface. It would appear so, since TypeScript is happy with the import and the type of <code>n</code> is <code>number</code>. (Naturally, if I actually ran this code, that wouldn't work — I haven't implemented <code>tjc</code> anywhere.)</p>
  <p>In the above, the type of <code>fourSource</code> is what you'd expect, it's picking up the four-source overload from lodash's types and so <code>fourSource</code>'s type is a union of those source object types (and the <code>{}</code> target). The type of <code>fiveSource</code> is <code>unknown</code>, though, because (apparently) it picks up the catch-all <code>extend</code> at the end of the original module's definition, not my added overload, and since I haven't provided a type argument for <code>TResult</code> it's had to punt on the inference.</p>
  <p>If I go into <code>@types/lodash/common/object.d.ts</code> and comment out the catch-all, my new overload gets picked up just fine. This is my &quot;proof&quot; (such as it is) that the catch-all is getting in the way.</p>
  <p>I can't think of a way of setting this up in the TypeScript playground (or, of course, on-site Stack Snippets), but I've done a <a href="https://stackblitz.com/edit/typescript-rzmyvh?file=test.ts" rel="nofollow noreferrer">stackblitz</a> with the code above, or of course if you create a project with TypeScript, install <code>lodash</code> and <code>@types/lodash</code>, and then drop the <code>lodash-extensions.d.ts</code> and <code>test.ts</code> files above into it, it should replicate the problem locally.</p>
  <p>I can think of a number of workarounds, like declaring my own <code>extends</code> that is really just a reference to lodash's and specifying the overloads. But is it possible to add my overload so it gets picked up when using <code>extends</code>, and if so, how?</p>