title: How do I express partial function application in Typescript 3.x in a type-safe way?
body: <p>I'm working on an Angular codebase that does some standard postprocessing on most API calls. This is done in a service class that wraps <code>HttpClient.get()</code> etc. in methods that pipe the returned observable through a bunch of intercepting methods.</p>
  
  <p>To my dismay this is done using the pattern:</p>
  
  <pre><code>public get(url, options?) {
    const method = 'GET';
    return this._http.get(url, options).pipe(
      map((resp: any) =&gt; {
        console.log(`Calling ${method} ${url} returned`, resp);
        return resp;
      }),
      catchError(err =&gt; {
        console.error(`Calling ${method} ${url} failed`, err);
        throw(err);
      }),
    );
  }
  </code></pre>
  
  <p>which annoys me, because the options parameter has a fairly hairy type the exact shape of which is important for TypeScript's overload resolution and determines the return type of the call. </p>
  
  <p>I'm trying to figure out a less copy-pastey, typesafe way of wrapping the call, but I can't figure out how to capture the type of the options parameter.</p>
  
  <p>What I have so far is: </p>
  
  <pre><code>export class HelloComponent {
    @Input() name: string;
    response: any;
  
    constructor(private _http: HttpClient) {
      const httpClientGet = this.method('get');
  
      const response = this.call('get', 'https://example.com/foo/bar');
  
      response.subscribe(
        data =&gt; this.response = JSON.stringify(data, null, 2),
        (err: HttpErrorResponse) =&gt; this.response = err.error
      );
  
    }
  
    call&lt;T&gt;(
      method: keyof HttpClient,
      url: string,
      handler: &lt;TObs extends Observable&lt;T&gt;&gt;(partial: (options?: any) =&gt; TObs) =&gt; TObs = (_ =&gt; _())) /* HOW DO I GET THE CORRECT TYPE OF OPTIONS HERE? */
      : Observable&lt;T&gt; {
  
      const u = new URL(url);
      console.info(`Calling ${method.toUpperCase()} ${u.pathname}`);
  
      const result = handler(this._http[method].bind(this._http, url)).pipe(
        map((resp) =&gt; {
          console.log(`Calling ${method.toUpperCase()} ${u.pathname} returned`, resp);
          return resp;
        }),
        catchError(err =&gt; {
          console.error(`Calling ${method.toUpperCase()} ${u.pathname} failed`, err);
          throw err;
        })
      )
  
      console.info('Returning', result);
      return result;
    }
  
    method&lt;TMethod extends keyof HttpClient&gt;(name: TMethod): HttpClient[TMethod] {
      return this._http[name];
    }
  }
  </code></pre>
  
  <p>That is:</p>
  
  <ul>
  <li>I know I can capture the signature of the method I'm calling on <code>HttpClient</code> by passing its name as a string literal to a method correctly, hovering over <code>httpClientGet</code> gives me the overloads for <code>HttpClient.get()</code></li>
  <li><code>call()</code> is the wrapper function that does the sameish interception as the original, but passes <code>HttpClient.get()</code> with the URL already partially applied using <code>Function.bind()</code> to an optional callback.</li>
  <li>The role of this callback is to provide the value of the <code>options</code> parameter to from the HttpClient methods if the caller wants to.</li>
  </ul>
  
  <p>Where I'm lost is figuring out what the right construct is to tell TypeScript that the parameters of the <code>partial</code> callback should be the parameters of the corresponding <code>HttpClient</code> method, <em>except</em> the first (<code>url</code>) parameter. Or some alternative way letting me do this in a type-safe fashion, i.e. autocomplete and overload resolution should work correctly if I do:</p>
  
  <pre><code>this.call('get', 'https://example.com/foo/bar',
    get =&gt; get({
      // options for `HttpClient.get()`
    })
  );
  </code></pre>
  
  <p>Stackblitz link for a runnable example of the above: <a href="https://stackblitz.com/edit/httpclient-partial" rel="nofollow noreferrer">https://stackblitz.com/edit/httpclient-partial</a></p>