title: Typescript function to omit certain keys and add others from it's argument
body: <p>I'm writing a function whose job it is to take a raw api response and transform it into a shape that is more easily consumable in my app (let's call it a "pretty" response).</p>
  
  <p>The code below is valid according to the TS compiler, but I want it to complain that I haven't removed the <code>metadata</code> key from the raw response before returning, as <code>metadata</code> exists in <code>RawResponse</code> but not in <code>PrettyResponse</code>.</p>
  
  <p>I thought that my <code>Optionalize</code> type would do this for me, but it doesn't seem to be working.</p>
  
  <p>What am I misunderstanding here?</p>
  
  <p>Here's a <a href="https://www.typescriptlang.org/play/?module=5&amp;ts=3.7.5&amp;ssl=18&amp;ssc=76&amp;pln=18&amp;pc=87#code/PTAEHkFsEsBdQGYCcD2lQBVSwBYFNQBrPATwGdRoA7UAYzUhRoHc4dQBpAWAChYSADgXADY0JgEMANtABeeADxY8AD1h4qAEwocANJwB8oALwQYsJfuIkUCQwG5evauqQIJtAgCUJzL3jIBJjICAG9eUEjQTQlYCQAuUABtAF1HHijQSDw4mLjE8AAjACs8Wlh0gF8nHhc8Nw8CAAUkHP5-QOCwiKi8hOS0nsiAN3qycSpEslgkagBzKprgACpliOXMCWJQCVAkXx2BaD2AoKoQna1sffOEFCR0OEoqWBQd0AFW2H5QJjwAOnWoAAglIpHsDq1OucAqAcBJRjt4FI8BJpth8ERSBRbKAfH5Tl1-qB1sBeAgAK5UcoTD4SJAhDpnEJKUCqdRaCj4pldAwACihzLwiQwAEoCqIJtI5IoMPpuYSYUYAGSgFptEg8mGgcIZKL0c7wKEUqTwUxFUrlf5o8ZzKh80KVfSCrr6XWZTKjBkTRIAcgAjAAmADMvqGoEqovSmRAoAAyjgUCbNFRffAAJJwhEEV7RPAo9QnMgm2D-bK5WK7Qp4O6tE6wClIKjzAD84a%20jZoxtNix4NTqDU8oAAsprFRd3b1K4lUtGolQJNkpjN5nPIuWJH0CiUyhVeNU%20zwDeiXTDEqOtRdTJPIluBrpwwul6A0wFYGRfQ%209eucpvpzqDwPXhj3gSASHVb4x2hK86QZPBL0UC9xzwflTxCKNgOCFAUX%20KQUDmPkwIg9pkIwnggA" rel="nofollow noreferrer">TS Playground link</a> to illustrate as well.</p>
  
  <pre class="lang-js prettyprint-override"><code>// Omit from T the keys in common with K
  type Optionalize&lt;T extends K, K&gt; = Omit&lt;T, keyof K&gt;;
  
  interface RawResponse {
      data: [];
      metadata: Object;
  }
  
  type PrettyResponse&lt;T extends RawResponse&gt; = Optionalize&lt;T, RawResponse&gt; &amp; {
      data: [];
      version: string;
  };
  
  /**
   * Take a raw api response and transform it into a pretty one.
   * All raw responses have at least the keys of RawResponse. 
   */
  function parseResponse&lt;T extends RawResponse&gt;(response: T): PrettyResponse&lt;T&gt; {
      const result = Object.assign({}, response, {
          version: '123'
      });
      // Shouldn't I have to delete result.metadata before returning?
      return result;
  }
  
  </code></pre>
  
  <p>And an example of consuming it:</p>
  
  <pre class="lang-js prettyprint-override"><code>interface MyResponse {
      data: [];
      name: string;
      category: string;
      other?: number;
      metadata: Object;
  }
  
  const response: MyResponse = {
      data: [],
      name: 'a',
      category: 'blah',
      metadata: {}
  }
  
  const myPrettyResponse: PrettyResponse&lt;MyResponse&gt; = parseResponse&lt;MyResponse&gt;(response);
  </code></pre>
  
  <p><em>Note: My colleague pointed out that this may be due to Typescript's use of <a href="https://www.typescriptlang.org/docs/handbook/type-compatibility.html" rel="nofollow noreferrer">structural subtyping</a>, but I would still expect the explicit return definition of <code>Optionalize&lt;T, RawResponse&gt;</code> to remove the <code>metadata</code> key.</em> </p>