title: How to properly type a higher order function
body: <p>I have a higher order function, for example in vanilla JS like this:</p>
  
  <pre><code>function log(fn) {
    return (...args) =&gt; {
      console.log("Calling", fn.name);
      return fn(...args);
    }
  }
  </code></pre>
  
  <p>And used like this:</p>
  
  <pre><code>let name;
  const setName = log((newName) =&gt; {
     name = newName;
  });
  setName("Hello"); // output "Calling setName"
  </code></pre>
  
  <p>How can I properly type this in TS such that <code>setName</code> has the correct function signature? Meaning:</p>
  
  <pre><code>setName("hello") // OK
  setName() // Error, missing arg
  setName(123) // Error, number not string
  </code></pre>
  
  <p>What I've come up with so far is:</p>
  
  <pre><code>function log&lt;F extends Function&gt;(fn: F): F {
    return (...args: any[]) =&gt; {
      console.log("Calling", fn.name);
      return fn(...args);
    }
  }
  
  let name;
  const setName = log((newName: string) =&gt; {
    name = newName;
  });
  </code></pre>
  
  <p>Which works the way I want (I get argument type checking on <code>setName</code>) but I get a compile error on the <code>log</code> function return:</p>
  
  <blockquote>
    <p>Error: TS2322:Type '(...args: any[]) => any' is not assignable to type 'F'.</p>
  </blockquote>
  
  <p>Even if I use <code>&lt;F extends (...args: any[]) =&gt; any&gt;</code> I get the same error. Basically, I don't know how to make the returned function satisfy the generic type <code>F</code>.</p>
  
  <p>How can I do this?</p>